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

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

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

revision 3, Fri Mar 8 02:46:11 2002 UTC revision 254, Wed Jul 3 12:32:50 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 133  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 141  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 159  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          const int search_range = 32 << (fcode - 1);          return NEIGH_TEND_8X8 * lambda_vec8[iQuant] * (mv_bits(dx, iFcode) +
274      const int high = search_range - 1;                                                                                                     mv_bits(dy, iFcode));
     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));  
275  }  }
276    
277    
 /* 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;  
         }  
 }  
   
278    
 /* This is somehow a copy of get_ref, but with MV instead of X,Y */  
279    
 static __inline const uint8_t * get_ref_mv(  
                                 const uint8_t * const refn,  
                                 const uint8_t * const refh,  
                                 const uint8_t * const refv,  
                                 const uint8_t * const refhv,  
                                 const uint32_t x, const uint32_t y,  
                                 const uint32_t block,                   // block dimension, 8 or 16  
                                 const VECTOR* mv,       // measured in half-pel!  
                                 const uint32_t stride)  
 {  
         switch ( (((mv->x)&1)<<1) + ((mv->y)&1) )  
     {  
         case 0 : return refn + (x*block+(mv->x)/2) + (y*block+(mv->y)/2)*stride;  
         case 1 : return refv + (x*block+(mv->x)/2) + (y*block+((mv->y)-1)/2)*stride;  
         case 2 : return refh + (x*block+((mv->x)-1)/2) + (y*block+(mv->y)/2)*stride;  
         default :  
         case 3 : return refhv + (x*block+((mv->x)-1)/2) + (y*block+((mv->y)-1)/2)*stride;  
         }  
 }  
280    
281  #ifndef SEARCH16  #ifndef SEARCH16
282  #define SEARCH16        PMVfastSearch16  #define SEARCH16        PMVfastSearch16
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;  
   
333    
334                  /* decide: MODE_INTER or MODE_INTRA                                  if (deviation < (pMB->sad16 - MV16_INTER_BIAS)) {
                         if (dev_intra < sad_inter - 2 * nb) use_intra  
                 */  
   
                 deviation = dev16(pCurrent->y + j*16 + i*16*pParam->edged_width, pParam->edged_width);  
   
                 if (deviation < (sad16 - 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 312  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 400  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 410  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 418  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 439  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 449  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 464  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;          VECTOR pred;
532    
533    
534          get_pmv(pMBs, x, y, pParam->mb_width, 0, &pred_x, &pred_y);          pred = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
535    
536          iSAD = sad16( cur,          iSAD = sad16( cur,
537                  get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0,0, iEdgedWidth),                  get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0,0, iEdgedWidth),
# Line 485  Line 541 
541    
542          currMV->x = 0;          currMV->x = 0;
543          currMV->y = 0;          currMV->y = 0;
544          currPMV->x = -pred_x;          currPMV->x = -pred.x;
545          currPMV->y = -pred_y;          currPMV->y = -pred.y;
546    
547          return iSAD;          return iSAD;
548    
549  }  }
550  */  */
551    
552  int32_t PMVfastSearch16_MainSearch(  int32_t
553                                          const uint8_t * const pRef,  Diamond16_MainSearch(const uint8_t * const pRef,
554                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
555                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
556                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
557                                          const uint8_t * const cur,                                          const uint8_t * const cur,
558                                          const int x, const int y,                                           const int x,
559                                          int32_t startx, int32_t starty,                                           const int y,
560                                             int32_t startx,
561                                             int32_t starty,
562                                          int32_t iMinSAD,                                          int32_t iMinSAD,
563                                          VECTOR * const currMV,                                          VECTOR * const currMV,
564                                          const VECTOR * const pmv,                                          const VECTOR * const pmv,
565                                          const int32_t min_dx, const int32_t max_dx,                                           const int32_t min_dx,
566                                          const int32_t min_dy, const int32_t max_dy,                                           const int32_t max_dx,
567                                             const int32_t min_dy,
568                                             const int32_t max_dy,
569                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
570                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
571                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 517  Line 577 
577          int32_t iDirection=0;          int32_t iDirection=0;
578          int32_t iSAD;          int32_t iSAD;
579          VECTOR backupMV;          VECTOR backupMV;
580    
581          backupMV.x = startx;          backupMV.x = startx;
582          backupMV.y = starty;          backupMV.y = starty;
583    
# Line 528  Line 589 
589          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
590    
591          if (iDirection)          if (iDirection)
592                  while (!iFound)                  while (!iFound) {
                 {  
593                          iFound = 1;                          iFound = 1;
594                          backupMV=*currMV;                          backupMV=*currMV;
595    
596                          if ( iDirection != 2)                          if ( iDirection != 2)
597                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
598                                                                                       backupMV.y, 1);
599                          if ( iDirection != 1)                          if ( iDirection != 1)
600                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
601                                                                                       backupMV.y, 2);
602                          if ( iDirection != 4)                          if ( iDirection != 4)
603                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
604                                                                                       backupMV.y - iDiamondSize, 3);
605                          if ( iDirection != 3)                          if ( iDirection != 3)
606                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
607                  }                                                                                     backupMV.y + iDiamondSize, 4);
608          else          } else {
                 {  
609                          currMV->x = startx;                          currMV->x = startx;
610                          currMV->y = starty;                          currMV->y = starty;
611                  }                  }
612          return iMinSAD;          return iMinSAD;
613  }  }
614    
615  int32_t PMVfastSearch16_Refine(  int32_t
616                                          const uint8_t * const pRef,  Square16_MainSearch(const uint8_t * const pRef,
617                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
618                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
619                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
620                                          const uint8_t * const cur,                                          const uint8_t * const cur,
621                                          const int x, const int y,                                          const int x,
622                                          VECTOR * const currMV,                                          const int y,
623                                            int32_t startx,
624                                            int32_t starty,
625                                          int32_t iMinSAD,                                          int32_t iMinSAD,
626                                            VECTOR * const currMV,
627                                          const VECTOR * const pmv,                                          const VECTOR * const pmv,
628                                          const int32_t min_dx, const int32_t max_dx,                                          const int32_t min_dx,
629                                          const int32_t min_dy, const int32_t max_dy,                                          const int32_t max_dx,
630                                            const int32_t min_dy,
631                                            const int32_t max_dy,
632                                            const int32_t iEdgedWidth,
633                                            const int32_t iDiamondSize,
634                                          const int32_t iFcode,                                          const int32_t iFcode,
635                                          const int32_t iQuant,                                          const int32_t iQuant,
636                                          const int32_t iEdgedWidth)                                          int iFound)
637  {  {
638  /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */  /* Do a square search around given starting point, return SAD of best */
639    
640            int32_t iDirection = 0;
641          int32_t iSAD;          int32_t iSAD;
642          VECTOR backupMV = *currMV;          VECTOR backupMV;
643    
644          CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y-1);          backupMV.x = startx;
645          CHECK_MV16_CANDIDATE(backupMV.x  ,backupMV.y-1);          backupMV.y = starty;
646          CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y-1);  
647          CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y);  /* It's one search with full square pattern, and new parts for all following diamonds */
648          CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y);  
649          CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y+1);  /*   new direction are extra, so 1-4 is normal diamond
650          CHECK_MV16_CANDIDATE(backupMV.x  ,backupMV.y+1);        537
651          CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y+1);        1*2
652          648
653    */
654    
655            CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y, 1);
656            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y, 2);
657            CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);
658            CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);
659    
660            CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
661                                                             backupMV.y - iDiamondSize, 5);
662            CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
663                                                             backupMV.y + iDiamondSize, 6);
664            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
665                                                             backupMV.y - iDiamondSize, 7);
666            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
667                                                             backupMV.y + iDiamondSize, 8);
668    
669    
670            if (iDirection)
671                    while (!iFound) {
672                            iFound = 1;
673                            backupMV = *currMV;
674    
675                            switch (iDirection) {
676                            case 1:
677                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
678                                                                                       backupMV.y, 1);
679                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
680                                                                                     backupMV.y - iDiamondSize, 5);
681                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
682                                                                                     backupMV.y - iDiamondSize, 7);
683                                    break;
684                            case 2:
685                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y,
686                                                                                     2);
687                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
688                                                                                     backupMV.y + iDiamondSize, 6);
689                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
690                                                                                     backupMV.y + iDiamondSize, 8);
691                                    break;
692    
693                            case 3:
694                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize,
695                                                                                     4);
696                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
697                                                                                     backupMV.y - iDiamondSize, 7);
698                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
699                                                                                     backupMV.y + iDiamondSize, 8);
700                                    break;
701    
702                            case 4:
703                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize,
704                                                                                     3);
705                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
706                                                                                     backupMV.y - iDiamondSize, 5);
707                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
708                                                                                     backupMV.y + iDiamondSize, 6);
709                                    break;
710    
711                            case 5:
712                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y,
713                                                                                     1);
714                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize,
715                                                                                     3);
716                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
717                                                                                     backupMV.y - iDiamondSize, 5);
718                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
719                                                                                     backupMV.y + iDiamondSize, 6);
720                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
721                                                                                     backupMV.y - iDiamondSize, 7);
722                                    break;
723    
724                            case 6:
725                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y,
726                                                                                     2);
727                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize,
728                                                                                     3);
729    
730                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
731                                                                                     backupMV.y - iDiamondSize, 5);
732                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
733                                                                                     backupMV.y + iDiamondSize, 6);
734                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
735                                                                                     backupMV.y + iDiamondSize, 8);
736    
737                                    break;
738    
739                            case 7:
740                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
741                                                                                       backupMV.y, 1);
742                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize,
743                                                                                     4);
744                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
745                                                                                     backupMV.y - iDiamondSize, 5);
746                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
747                                                                                     backupMV.y - iDiamondSize, 7);
748                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
749                                                                                     backupMV.y + iDiamondSize, 8);
750                                    break;
751    
752                            case 8:
753                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y,
754                                                                                     2);
755                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize,
756                                                                                     4);
757                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
758                                                                                     backupMV.y + iDiamondSize, 6);
759                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
760                                                                                     backupMV.y - iDiamondSize, 7);
761                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
762                                                                                     backupMV.y + iDiamondSize, 8);
763                                    break;
764                            default:
765                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y,
766                                                                                     1);
767                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y,
768                                                                                     2);
769                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize,
770                                                                                     3);
771                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize,
772                                                                                     4);
773    
774                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
775                                                                                     backupMV.y - iDiamondSize, 5);
776                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
777                                                                                     backupMV.y + iDiamondSize, 6);
778                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
779                                                                                     backupMV.y - iDiamondSize, 7);
780                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
781                                                                                     backupMV.y + iDiamondSize, 8);
782                                    break;
783                            }
784            } else {
785                    currMV->x = startx;
786                    currMV->y = starty;
787            }
788          return iMinSAD;          return iMinSAD;
789  }  }
790    
 #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)  
791    
792  int32_t PMVfastSearch16(  int32_t
793                                          const uint8_t * const pRef,  Full16_MainSearch(const uint8_t * const pRef,
794                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
795                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
796                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
797                                          const IMAGE * const pCur,                                    const uint8_t * const cur,
798                                          const int x, const int y,                                    const int x,
799                                          const uint32_t MotionFlags,                                    const int y,
800                                          MBParam * const pParam,                                    int32_t startx,
801                                          MACROBLOCK * const pMBs,                                    int32_t starty,
802                                      int32_t iMinSAD,
803                                          VECTOR * const currMV,                                          VECTOR * const currMV,
804                                          VECTOR * const currPMV)                                    const VECTOR * const pmv,
805                                      const int32_t min_dx,
806                                      const int32_t max_dx,
807                                      const int32_t min_dy,
808                                      const int32_t max_dy,
809                                      const int32_t iEdgedWidth,
810                                      const int32_t iDiamondSize,
811                                      const int32_t iFcode,
812                                      const int32_t iQuant,
813                                      int iFound)
814  {  {
815          const uint32_t iWcount = pParam->mb_width;          int32_t iSAD;
816          const int32_t iFcode = pParam->fixed_code;          int32_t dx, dy;
817          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;  
   
         int32_t min_dx;  
         int32_t max_dx;  
         int32_t min_dy;  
         int32_t max_dy;  
818    
819          int32_t iFound;          backupMV.x = startx;
820            backupMV.y = starty;
821    
822          VECTOR newMV;          for (dx = min_dx; dx <= max_dx; dx += iDiamondSize)
823          VECTOR backupMV;        /* just for PMVFAST */                  for (dy = min_dy; dy <= max_dy; dy += iDiamondSize)
824                            NOCHECK_MV16_CANDIDATE(dx, dy);
825    
826          VECTOR pmv[4];          return iMinSAD;
827          int32_t psad[4];  }
828    
829          MACROBLOCK * const pMB = pMBs + x + y * iWcount;  int32_t
830    AdvDiamond16_MainSearch(const uint8_t * const pRef,
831                                                    const uint8_t * const pRefH,
832                                                    const uint8_t * const pRefV,
833                                                    const uint8_t * const pRefHV,
834                                                    const uint8_t * const cur,
835                                                    const int x,
836                                                    const int y,
837                                                    int32_t startx,
838                                                    int32_t starty,
839                                                    int32_t iMinSAD,
840                                                    VECTOR * const currMV,
841                                                    const VECTOR * const pmv,
842                                                    const int32_t min_dx,
843                                                    const int32_t max_dx,
844                                                    const int32_t min_dy,
845                                                    const int32_t max_dy,
846                                                    const int32_t iEdgedWidth,
847                                                    const int32_t iDiamondSize,
848                                                    const int32_t iFcode,
849                                                    const int32_t iQuant,
850                                                    int iDirection)
851    {
852    
853          static int32_t threshA,threshB;          int32_t iSAD;
         int32_t bPredEq;  
         int32_t iMinSAD,iSAD;  
854    
855  /* Get maximum range */  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
         get_range(&min_dx, &max_dx, &min_dy, &max_dy,  
                         x, y, 16, iWidth, iHeight, iFcode);  
856    
857  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */          if (iDirection) {
858                    CHECK_MV16_CANDIDATE(startx - iDiamondSize, starty);
859                    CHECK_MV16_CANDIDATE(startx + iDiamondSize, starty);
860                    CHECK_MV16_CANDIDATE(startx, starty - iDiamondSize);
861                    CHECK_MV16_CANDIDATE(startx, starty + iDiamondSize);
862            } else {
863                    int bDirection = 1 + 2 + 4 + 8;
864    
865                    do {
866                            iDirection = 0;
867                            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)
868                                    CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize, starty, 1);
869    
870                            if (bDirection & 2)
871                                    CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize, starty, 2);
872    
873                            if (bDirection & 4)
874                                    CHECK_MV16_CANDIDATE_DIR(startx, starty - iDiamondSize, 4);
875    
876                            if (bDirection & 8)
877                                    CHECK_MV16_CANDIDATE_DIR(startx, starty + iDiamondSize, 8);
878    
879                            /* now we're doing diagonal checks near our candidate */
880    
881                            if (iDirection)         //checking if anything found
882                            {
883                                    bDirection = iDirection;
884                                    iDirection = 0;
885                                    startx = currMV->x;
886                                    starty = currMV->y;
887                                    if (bDirection & 3)     //our candidate is left or right
888                                    {
889                                            CHECK_MV16_CANDIDATE_DIR(startx, starty + iDiamondSize, 8);
890                                            CHECK_MV16_CANDIDATE_DIR(startx, starty - iDiamondSize, 4);
891                                    } else                  // what remains here is up or down
892                                    {
893                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize, starty, 2);
894                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize, starty, 1);
895                                    }
896    
897                                    if (iDirection) {
898                                            bDirection += iDirection;
899                                            startx = currMV->x;
900                                            starty = currMV->y;
901                                    }
902                            } else                          //about to quit, eh? not so fast....
903                            {
904                                    switch (bDirection) {
905                                    case 2:
906                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
907                                                                                             starty - iDiamondSize, 2 + 4);
908                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
909                                                                                             starty + iDiamondSize, 2 + 8);
910                                            break;
911                                    case 1:
912                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
913                                                                                             starty - iDiamondSize, 1 + 4);
914                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
915                                                                                             starty + iDiamondSize, 1 + 8);
916                                            break;
917                                    case 2 + 4:
918                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
919                                                                                             starty - iDiamondSize, 1 + 4);
920                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
921                                                                                             starty - iDiamondSize, 2 + 4);
922                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
923                                                                                             starty + iDiamondSize, 2 + 8);
924                                            break;
925                                    case 4:
926                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
927                                                                                             starty - iDiamondSize, 2 + 4);
928                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
929                                                                                             starty - iDiamondSize, 1 + 4);
930                                            break;
931                                    case 8:
932                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
933                                                                                             starty + iDiamondSize, 2 + 8);
934                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
935                                                                                             starty + iDiamondSize, 1 + 8);
936                                            break;
937                                    case 1 + 4:
938                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
939                                                                                             starty + iDiamondSize, 1 + 8);
940                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
941                                                                                             starty - iDiamondSize, 1 + 4);
942                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
943                                                                                             starty - iDiamondSize, 2 + 4);
944                                            break;
945                                    case 2 + 8:
946                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
947                                                                                             starty - iDiamondSize, 1 + 4);
948                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
949                                                                                             starty + iDiamondSize, 1 + 8);
950                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
951                                                                                             starty + iDiamondSize, 2 + 8);
952                                            break;
953                                    case 1 + 8:
954                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
955                                                                                             starty - iDiamondSize, 2 + 4);
956                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
957                                                                                             starty + iDiamondSize, 2 + 8);
958                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
959                                                                                             starty + iDiamondSize, 1 + 8);
960                                            break;
961                                    default:                //1+2+4+8 == we didn't find anything at all
962                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
963                                                                                             starty - iDiamondSize, 1 + 4);
964                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
965                                                                                             starty + iDiamondSize, 1 + 8);
966                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
967                                                                                             starty - iDiamondSize, 2 + 4);
968                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
969                                                                                             starty + iDiamondSize, 2 + 8);
970                                            break;
971                                    }
972                                    if (!iDirection)
973                                            break;          //ok, the end. really
974                                    else {
975                                            bDirection = iDirection;
976                                            startx = currMV->x;
977                                            starty = currMV->y;
978                                    }
979                            }
980                    }
981                    while (1);                              //forever
982            }
983            return iMinSAD;
984    }
985    
986          if (!(MotionFlags & PMV_HALFPEL16 ))  int32_t
987          { min_dx = EVEN(min_dx);  AdvDiamond8_MainSearch(const uint8_t * const pRef,
988            max_dx = EVEN(max_dx);                                             const uint8_t * const pRefH,
989            min_dy = EVEN(min_dy);                                             const uint8_t * const pRefV,
990            max_dy = EVEN(max_dy);                                             const uint8_t * const pRefHV,
991          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */                                             const uint8_t * const cur,
992                                               const int x,
993                                               const int y,
994                                               int32_t startx,
995                                               int32_t starty,
996                                               int32_t iMinSAD,
997                                               VECTOR * const currMV,
998                                               const VECTOR * const pmv,
999                                               const int32_t min_dx,
1000                                               const int32_t max_dx,
1001                                               const int32_t min_dy,
1002                                               const int32_t max_dy,
1003                                               const int32_t iEdgedWidth,
1004                                               const int32_t iDiamondSize,
1005                                               const int32_t iFcode,
1006                                               const int32_t iQuant,
1007                                               int iDirection)
1008    {
1009    
1010            int32_t iSAD;
1011    
1012          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
1013    
1014          if ((x==0) && (y==0) )          if (iDirection) {
1015                    CHECK_MV8_CANDIDATE(startx - iDiamondSize, starty);
1016                    CHECK_MV8_CANDIDATE(startx + iDiamondSize, starty);
1017                    CHECK_MV8_CANDIDATE(startx, starty - iDiamondSize);
1018                    CHECK_MV8_CANDIDATE(startx, starty + iDiamondSize);
1019            } else {
1020                    int bDirection = 1 + 2 + 4 + 8;
1021    
1022                    do {
1023                            iDirection = 0;
1024                            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)
1025                                    CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize, starty, 1);
1026    
1027                            if (bDirection & 2)
1028                                    CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize, starty, 2);
1029    
1030                            if (bDirection & 4)
1031                                    CHECK_MV8_CANDIDATE_DIR(startx, starty - iDiamondSize, 4);
1032    
1033                            if (bDirection & 8)
1034                                    CHECK_MV8_CANDIDATE_DIR(startx, starty + iDiamondSize, 8);
1035    
1036                            /* now we're doing diagonal checks near our candidate */
1037    
1038                            if (iDirection)         //checking if anything found
1039                            {
1040                                    bDirection = iDirection;
1041                                    iDirection = 0;
1042                                    startx = currMV->x;
1043                                    starty = currMV->y;
1044                                    if (bDirection & 3)     //our candidate is left or right
1045                                    {
1046                                            CHECK_MV8_CANDIDATE_DIR(startx, starty + iDiamondSize, 8);
1047                                            CHECK_MV8_CANDIDATE_DIR(startx, starty - iDiamondSize, 4);
1048                                    } else                  // what remains here is up or down
1049                                    {
1050                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize, starty, 2);
1051                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize, starty, 1);
1052                                    }
1053    
1054                                    if (iDirection) {
1055                                            bDirection += iDirection;
1056                                            startx = currMV->x;
1057                                            starty = currMV->y;
1058                                    }
1059                            } else                          //about to quit, eh? not so fast....
1060                            {
1061                                    switch (bDirection) {
1062                                    case 2:
1063                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
1064                                                                                            starty - iDiamondSize, 2 + 4);
1065                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
1066                                                                                            starty + iDiamondSize, 2 + 8);
1067                                            break;
1068                                    case 1:
1069                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
1070                                                                                            starty - iDiamondSize, 1 + 4);
1071                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
1072                                                                                            starty + iDiamondSize, 1 + 8);
1073                                            break;
1074                                    case 2 + 4:
1075                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
1076                                                                                            starty - iDiamondSize, 1 + 4);
1077                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
1078                                                                                            starty - iDiamondSize, 2 + 4);
1079                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
1080                                                                                            starty + iDiamondSize, 2 + 8);
1081                                            break;
1082                                    case 4:
1083                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
1084                                                                                            starty - iDiamondSize, 2 + 4);
1085                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
1086                                                                                            starty - iDiamondSize, 1 + 4);
1087                                            break;
1088                                    case 8:
1089                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
1090                                                                                            starty + iDiamondSize, 2 + 8);
1091                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
1092                                                                                            starty + iDiamondSize, 1 + 8);
1093                                            break;
1094                                    case 1 + 4:
1095                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
1096                                                                                            starty + iDiamondSize, 1 + 8);
1097                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
1098                                                                                            starty - iDiamondSize, 1 + 4);
1099                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
1100                                                                                            starty - iDiamondSize, 2 + 4);
1101                                            break;
1102                                    case 2 + 8:
1103                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
1104                                                                                            starty - iDiamondSize, 1 + 4);
1105                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
1106                                                                                            starty + iDiamondSize, 1 + 8);
1107                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
1108                                                                                            starty + iDiamondSize, 2 + 8);
1109                                            break;
1110                                    case 1 + 8:
1111                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
1112                                                                                            starty - iDiamondSize, 2 + 4);
1113                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
1114                                                                                            starty + iDiamondSize, 2 + 8);
1115                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
1116                                                                                            starty + iDiamondSize, 1 + 8);
1117                                            break;
1118                                    default:                //1+2+4+8 == we didn't find anything at all
1119                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
1120                                                                                            starty - iDiamondSize, 1 + 4);
1121                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
1122                                                                                            starty + iDiamondSize, 1 + 8);
1123                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
1124                                                                                            starty - iDiamondSize, 2 + 4);
1125                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
1126                                                                                            starty + iDiamondSize, 2 + 8);
1127                                            break;
1128                                    }
1129                                    if (!(iDirection))
1130                                            break;          //ok, the end. really
1131                                    else {
1132                                            bDirection = iDirection;
1133                                            startx = currMV->x;
1134                                            starty = currMV->y;
1135                                    }
1136                            }
1137                    }
1138                    while (1);                              //forever
1139            }
1140            return iMinSAD;
1141    }
1142    
1143    
1144    int32_t
1145    Full8_MainSearch(const uint8_t * const pRef,
1146                                     const uint8_t * const pRefH,
1147                                     const uint8_t * const pRefV,
1148                                     const uint8_t * const pRefHV,
1149                                     const uint8_t * const cur,
1150                                     const int x,
1151                                     const int y,
1152                                     int32_t startx,
1153                                     int32_t starty,
1154                                     int32_t iMinSAD,
1155                                     VECTOR * const currMV,
1156                                     const VECTOR * const pmv,
1157                                     const int32_t min_dx,
1158                                     const int32_t max_dx,
1159                                     const int32_t min_dy,
1160                                     const int32_t max_dy,
1161                                     const int32_t iEdgedWidth,
1162                                     const int32_t iDiamondSize,
1163                                     const int32_t iFcode,
1164                                     const int32_t iQuant,
1165                                     int iFound)
1166          {          {
1167                  threshA =  512;          int32_t iSAD;
1168                  threshB = 1024;          int32_t dx, dy;
1169            VECTOR backupMV;
1170    
1171            backupMV.x = startx;
1172            backupMV.y = starty;
1173    
1174            for (dx = min_dx; dx <= max_dx; dx += iDiamondSize)
1175                    for (dy = min_dy; dy <= max_dy; dy += iDiamondSize)
1176                            NOCHECK_MV8_CANDIDATE(dx, dy);
1177    
1178            return iMinSAD;
1179          }          }
1180          else  
1181    
1182    
1183    int32_t
1184    Halfpel16_Refine(const uint8_t * const pRef,
1185                                     const uint8_t * const pRefH,
1186                                     const uint8_t * const pRefV,
1187                                     const uint8_t * const pRefHV,
1188                                     const uint8_t * const cur,
1189                                     const int x,
1190                                     const int y,
1191                                     VECTOR * const currMV,
1192                                     int32_t iMinSAD,
1193                                     const VECTOR * const pmv,
1194                                     const int32_t min_dx,
1195                                     const int32_t max_dx,
1196                                     const int32_t min_dy,
1197                                     const int32_t max_dy,
1198                                     const int32_t iFcode,
1199                                     const int32_t iQuant,
1200                                     const int32_t iEdgedWidth)
1201          {          {
1202                  threshA = psad[0];  /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */
1203                  threshB = threshA+256;  
1204                  if (threshA< 512) threshA =  512;          int32_t iSAD;
1205                  if (threshA>1024) threshA = 1024;          VECTOR backupMV = *currMV;
1206                  if (threshB>1792) threshB = 1792;  
1207            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y - 1);
1208            CHECK_MV16_CANDIDATE(backupMV.x, backupMV.y - 1);
1209            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y - 1);
1210            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y);
1211            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y);
1212            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y + 1);
1213            CHECK_MV16_CANDIDATE(backupMV.x, backupMV.y + 1);
1214            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y + 1);
1215    
1216            return iMinSAD;
1217          }          }
1218    
1219          iFound=0;  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
1220    
 /* 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  
 */  
1221    
1222          if ((bPredEq) && (MVequal(pmv[0],pMB->mvs[0]) ) )  int32_t
1223                  iFound=2;  PMVfastSearch16(const uint8_t * const pRef,
1224                                    const uint8_t * const pRefH,
1225                                    const uint8_t * const pRefV,
1226                                    const uint8_t * const pRefHV,
1227                                    const IMAGE * const pCur,
1228                                    const int x,
1229                                    const int y,
1230                                    const uint32_t MotionFlags,
1231                                    const uint32_t iQuant,
1232                                    const uint32_t iFcode,
1233                                    const MBParam * const pParam,
1234                                    const MACROBLOCK * const pMBs,
1235                                    const MACROBLOCK * const prevMBs,
1236                                    VECTOR * const currMV,
1237                                    VECTOR * const currPMV)
1238    {
1239            const uint32_t iWcount = pParam->mb_width;
1240            const int32_t iWidth = pParam->width;
1241            const int32_t iHeight = pParam->height;
1242            const int32_t iEdgedWidth = pParam->edged_width;
1243    
1244  /* 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.  
 */  
1245    
1246          if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536) || (bPredEq) )          int32_t iDiamondSize;
                 iDiamondSize=1; // halfpel!  
         else  
                 iDiamondSize=2; // halfpel!  
1247    
1248          if (!(MotionFlags & PMV_HALFPELDIAMOND16) )          int32_t min_dx;
1249                  iDiamondSize*=2;          int32_t max_dx;
1250            int32_t min_dy;
1251            int32_t max_dy;
1252    
1253            int32_t iFound;
1254    
1255            VECTOR newMV;
1256            VECTOR backupMV;                        /* just for PMVFAST */
1257    
1258            VECTOR pmv[4];
1259            int32_t psad[4];
1260    
1261            MainSearch16FuncPtr MainSearchPtr;
1262    
1263    //  const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
1264            const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
1265    
1266            static int32_t threshA, threshB;
1267            int32_t bPredEq;
1268            int32_t iMinSAD, iSAD;
1269    
1270    /* Get maximum range */
1271            get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
1272                              iFcode);
1273    
1274    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
1275    
1276            if (!(MotionFlags & PMV_HALFPEL16)) {
1277                    min_dx = EVEN(min_dx);
1278                    max_dx = EVEN(max_dx);
1279                    min_dy = EVEN(min_dy);
1280                    max_dy = EVEN(max_dy);
1281            }
1282    
1283            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1284            bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
1285            // bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
1286    
1287            if ((x == 0) && (y == 0)) {
1288                    threshA = 512;
1289                    threshB = 1024;
1290    
1291            } else {
1292                    threshA = psad[0];
1293                    threshB = threshA + 256;
1294                    if (threshA < 512)
1295                            threshA = 512;
1296                    if (threshA > 1024)
1297                            threshA = 1024;
1298                    if (threshB > 1792)
1299                            threshB = 1792;
1300            }
1301    
1302            iFound = 0;
1303    
1304  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
1305          MinSAD=SAD          MinSAD=SAD
# Line 688  Line 1308 
1308          If SAD<=256 goto Step 10.          If SAD<=256 goto Step 10.
1309  */  */
1310    
   
 // Prepare for main loop  
   
1311          *currMV=pmv[0];         /* current best := prediction */          *currMV=pmv[0];         /* current best := prediction */
1312          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16)) {   /* This should NOT be necessary! */
         {       /* This should NOT be necessary! */  
1313                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
1314                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
1315          }          }
1316    
1317          if (currMV->x > max_dx)          if (currMV->x > max_dx) {
                 {  
1318                          currMV->x=max_dx;                          currMV->x=max_dx;
1319                  }                  }
1320          if (currMV->x < min_dx)          if (currMV->x < min_dx) {
                 {  
1321                          currMV->x=min_dx;                          currMV->x=min_dx;
1322                  }                  }
1323          if (currMV->y > max_dy)          if (currMV->y > max_dy) {
                 {  
1324                          currMV->y=max_dy;                          currMV->y=max_dy;
1325                  }                  }
1326          if (currMV->y < min_dy)          if (currMV->y < min_dy) {
                 {  
1327                          currMV->y=min_dy;                          currMV->y=min_dy;
1328                  }                  }
1329    
1330          iMinSAD = sad16( cur,          iMinSAD =
1331                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  sad16(cur,
1332                  iEdgedWidth, MV_MAX_ERROR);                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
1333          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
1334            iMinSAD +=
1335          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && (iMinSAD < pMB->sad16) ) )                  calc_delta_16(currMV->x - pmv[0].x, currMV->y - pmv[0].y,
1336                  {                                            (uint8_t) iFcode, iQuant);
1337    
1338            if ((iMinSAD < 256) ||
1339                    ((MVequal(*currMV, prevMB->mvs[0])) &&
1340                     ((uint32_t) iMinSAD < prevMB->sad16))) {
1341                    if (iMinSAD < 2 * iQuant)       // high chances for SKIP-mode
1342                    {
1343                            if (!MVzero(*currMV)) {
1344                                    iMinSAD += MV16_00_BIAS;
1345                                    CHECK_MV16_ZERO;        // (0,0) saves space for letterboxed pictures
1346                                    iMinSAD -= MV16_00_BIAS;
1347                            }
1348                    }
1349    
1350                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
1351                                  goto step10b;                          goto PMVfast16_Terminate_without_Refine;
1352                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
1353                                  goto step10;                          goto PMVfast16_Terminate_with_Refine;
1354                  }                  }
1355    
1356    
1357    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
1358       vector of the median.
1359       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1360    */
1361    
1362            if ((bPredEq) && (MVequal(pmv[0], prevMB->mvs[0])))
1363                    iFound = 2;
1364    
1365    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
1366       Otherwise select large Diamond Search.
1367    */
1368    
1369            if ((!MVzero(pmv[0])) || (threshB < 1536) || (bPredEq))
1370                    iDiamondSize = 1;               // halfpel!
1371            else
1372                    iDiamondSize = 2;               // halfpel!
1373    
1374            if (!(MotionFlags & PMV_HALFPELDIAMOND16))
1375                    iDiamondSize *= 2;
1376    
1377  /*  /*
1378  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.
1379          Also calculate (0,0) but do not subtract offset.          Also calculate (0,0) but do not subtract offset.
1380          Let MinSAD be the smallest SAD up to this point.          Let MinSAD be the smallest SAD up to this point.
1381          If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
1382  */  */
1383    
1384  // (0,0) is always possible  // (0,0) is always possible
1385    
1386            if (!MVzero(pmv[0]))
1387          CHECK_MV16_ZERO;          CHECK_MV16_ZERO;
1388    
1389  // previous frame MV is always possible  // previous frame MV is always possible
1390          CHECK_MV16_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);  
1391            if (!MVzero(prevMB->mvs[0]))
1392                    if (!MVequal(prevMB->mvs[0], pmv[0]))
1393                            CHECK_MV16_CANDIDATE(prevMB->mvs[0].x, prevMB->mvs[0].y);
1394    
1395  // left neighbour, if allowed  // left neighbour, if allowed
1396          if (x != 0)  
1397          {          if (!MVzero(pmv[1]))
1398                  if (!(MotionFlags & PMV_HALFPEL16 ))                  if (!MVequal(pmv[1], prevMB->mvs[0]))
1399                  {       pmv[1].x = EVEN(pmv[1].x);                          if (!MVequal(pmv[1], pmv[0])) {
1400                                    if (!(MotionFlags & PMV_HALFPEL16)) {
1401                                            pmv[1].x = EVEN(pmv[1].x);
1402                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
1403                  }                  }
1404    
1405                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1406          }          }
   
1407  // top neighbour, if allowed  // top neighbour, if allowed
1408          if (y != 0)          if (!MVzero(pmv[2]))
1409          {                  if (!MVequal(pmv[2], prevMB->mvs[0]))
1410                  if (!(MotionFlags & PMV_HALFPEL16 ))                          if (!MVequal(pmv[2], pmv[0]))
1411                  {       pmv[2].x = EVEN(pmv[2].x);                                  if (!MVequal(pmv[2], pmv[1])) {
1412                                            if (!(MotionFlags & PMV_HALFPEL16)) {
1413                                                    pmv[2].x = EVEN(pmv[2].x);
1414                          pmv[2].y = EVEN(pmv[2].y);                          pmv[2].y = EVEN(pmv[2].y);
1415                  }                  }
1416                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1417    
1418  // top right neighbour, if allowed  // top right neighbour, if allowed
1419                  if (x != (iWcount-1))                                          if (!MVzero(pmv[3]))
1420                  {                                                  if (!MVequal(pmv[3], prevMB->mvs[0]))
1421                          if (!(MotionFlags & PMV_HALFPEL16 ))                                                          if (!MVequal(pmv[3], pmv[0]))
1422                          {       pmv[3].x = EVEN(pmv[3].x);                                                                  if (!MVequal(pmv[3], pmv[1]))
1423                                                                            if (!MVequal(pmv[3], pmv[2])) {
1424                                                                                    if (!(MotionFlags & PMV_HALFPEL16)) {
1425                                                                                            pmv[3].x = EVEN(pmv[3].x);
1426                                  pmv[3].y = EVEN(pmv[3].y);                                  pmv[3].y = EVEN(pmv[3].y);
1427                          }                          }
1428                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                  CHECK_MV16_CANDIDATE(pmv[3].x,
1429                                                                                                                             pmv[3].y);
1430                  }                  }
1431          }          }
1432    
1433            if ((MVzero(*currMV)) &&
1434                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1435                    iMinSAD -= MV16_00_BIAS;
1436    
1437    
1438  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
1439     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.
1440  */  */
1441    
1442          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[0]) && (iMinSAD < pMB->sad16) ) )          if ((iMinSAD <= threshA) ||
1443                  {                  (MVequal(*currMV, prevMB->mvs[0]) &&
1444                     ((uint32_t) iMinSAD < prevMB->sad16))) {
1445                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
1446                                  goto step10b;                          goto PMVfast16_Terminate_without_Refine;
1447                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
1448                                  goto step10;                          goto PMVfast16_Terminate_with_Refine;
1449                  }                  }
1450    
1451    
# Line 796  Line 1459 
1459          Refine by using small diamond and goto step 10.          Refine by using small diamond and goto step 10.
1460  */  */
1461    
1462            if (MotionFlags & PMV_USESQUARES16)
1463                    MainSearchPtr = Square16_MainSearch;
1464            else if (MotionFlags & PMV_ADVANCEDDIAMOND16)
1465                    MainSearchPtr = AdvDiamond16_MainSearch;
1466            else
1467                    MainSearchPtr = Diamond16_MainSearch;
1468    
1469          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1470    
1471  /* 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 */
1472          iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
1473                  x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
1474                  currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx,
1475                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
1476                                                      iQuant, iFound);
1477    
1478          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
1479                  *currMV = newMV;                  *currMV = newMV;
1480                  iMinSAD = iSAD;                  iMinSAD = iSAD;
1481          }          }
1482    
1483          if (MotionFlags & PMV_EXTSEARCH16)          if (MotionFlags & PMV_EXTSEARCH16) {
         {  
1484  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1485    
1486                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
1487                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1488                                  x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1489                          pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, pmv,
1490                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1491                                                                      iDiamondSize, iFcode, iQuant, iFound);
1492    
1493                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
1494                                  *currMV = newMV;                                  *currMV = newMV;
1495                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
1496                          }                          }
1497                  }                  }
1498    
1499                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
1500                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1501                                  x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
1502                          0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy,
1503                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
1504                                                                      iQuant, iFound);
1505    
1506                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
1507                                  *currMV = newMV;                                  *currMV = newMV;
1508                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
1509                          }                          }
# Line 845  Line 1514 
1514          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.
1515  */  */
1516    
1517  step10:    PMVfast16_Terminate_with_Refine:
1518          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
1519                  iMinSAD = PMVfastSearch16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
1520                                  x, y,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
1521                                  currMV, iMinSAD,                                                           iMinSAD, pmv, min_dx, max_dx, min_dy, max_dy,
1522                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                           iFcode, iQuant, iEdgedWidth);
1523    
1524  step10b:    PMVfast16_Terminate_without_Refine:
1525          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - pmv[0].x;
1526          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - pmv[0].y;
1527          return iMinSAD;          return iMinSAD;
# Line 863  Line 1532 
1532    
1533    
1534    
1535  int32_t PMVfastSearch8_MainSearch(  int32_t
1536                                          const uint8_t * const pRef,  Diamond8_MainSearch(const uint8_t * const pRef,
1537                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1538                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1539                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1540                                          const uint8_t * const cur,                                          const uint8_t * const cur,
1541                                          const int x, const int y,                                          const int x,
1542                                          int32_t startx, int32_t starty,                                          const int y,
1543                                            int32_t startx,
1544                                            int32_t starty,
1545                                          int32_t iMinSAD,                                          int32_t iMinSAD,
1546                                          VECTOR * const currMV,                                          VECTOR * const currMV,
1547                                          const VECTOR * const pmv,                                          const VECTOR * const pmv,
1548                                          const int32_t min_dx, const int32_t max_dx,                                          const int32_t min_dx,
1549                                          const int32_t min_dy, const int32_t max_dy,                                          const int32_t max_dx,
1550                                            const int32_t min_dy,
1551                                            const int32_t max_dy,
1552                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
1553                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
1554                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 887  Line 1560 
1560          int32_t iDirection=0;          int32_t iDirection=0;
1561          int32_t iSAD;          int32_t iSAD;
1562          VECTOR backupMV;          VECTOR backupMV;
1563    
1564          backupMV.x = startx;          backupMV.x = startx;
1565          backupMV.y = starty;          backupMV.y = starty;
1566    
# Line 898  Line 1572 
1572          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
1573    
1574          if (iDirection)          if (iDirection)
1575                  while (!iFound)                  while (!iFound) {
                 {  
1576                          iFound = 1;                          iFound = 1;
1577                          backupMV=*currMV;       // since iDirection!=0, this is well defined!                          backupMV=*currMV;       // since iDirection!=0, this is well defined!
1578    
1579                          if ( iDirection != 2)                          if ( iDirection != 2)
1580                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1581                                                                                      backupMV.y, 1);
1582                          if ( iDirection != 1)                          if ( iDirection != 1)
1583                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1584                                                                                      backupMV.y, 2);
1585                          if ( iDirection != 4)                          if ( iDirection != 4)
1586                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1587                                                                                      backupMV.y - iDiamondSize, 3);
1588                          if ( iDirection != 3)                          if ( iDirection != 3)
1589                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1590                  }                                                                                    backupMV.y + iDiamondSize, 4);
1591          else          } else {
                 {  
1592                          currMV->x = startx;                          currMV->x = startx;
1593                          currMV->y = starty;                          currMV->y = starty;
1594                  }                  }
1595          return iMinSAD;          return iMinSAD;
1596  }  }
1597    
1598  int32_t PMVfastSearch8_Refine(  int32_t
1599                                          const uint8_t * const pRef,  Halfpel8_Refine(const uint8_t * const pRef,
1600                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1601                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1602                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1603                                          const uint8_t * const cur,                                          const uint8_t * const cur,
1604                                          const int x, const int y,                                  const int x,
1605                                    const int y,
1606                                          VECTOR * const currMV,                                          VECTOR * const currMV,
1607                                          int32_t iMinSAD,                                          int32_t iMinSAD,
1608                                          const VECTOR * const pmv,                                          const VECTOR * const pmv,
1609                                          const int32_t min_dx, const int32_t max_dx,                                  const int32_t min_dx,
1610                                          const int32_t min_dy, const int32_t max_dy,                                  const int32_t max_dx,
1611                                    const int32_t min_dy,
1612                                    const int32_t max_dy,
1613                                          const int32_t iFcode,                                          const int32_t iFcode,
1614                                          const int32_t iQuant,                                          const int32_t iQuant,
1615                                          const int32_t iEdgedWidth)                                          const int32_t iEdgedWidth)
# Line 956  Line 1634 
1634    
1635  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)
1636    
1637  int32_t PMVfastSearch8(  int32_t
1638                                          const uint8_t * const pRef,  PMVfastSearch8(const uint8_t * const pRef,
1639                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1640                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1641                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1642                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1643                                          const int x, const int y,                             const int x,
1644                                          const int start_x, int start_y,                             const int y,
1645                               const int start_x,
1646                               const int start_y,
1647                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1648                                          MBParam * const pParam,                             const uint32_t iQuant,
1649                                          MACROBLOCK * const pMBs,                             const uint32_t iFcode,
1650                               const MBParam * const pParam,
1651                               const MACROBLOCK * const pMBs,
1652                               const MACROBLOCK * const prevMBs,
1653                                          VECTOR * const currMV,                                          VECTOR * const currMV,
1654                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
1655  {  {
1656          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;  
1657          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
1658          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
1659          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
# Line 991  Line 1671 
1671          int32_t psad[4];          int32_t psad[4];
1672          VECTOR newMV;          VECTOR newMV;
1673          VECTOR backupMV;          VECTOR backupMV;
1674            VECTOR startMV;
1675    
1676          MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;  //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1677            const MACROBLOCK *const prevMB = prevMBs + (x >> 1) + (y >> 1) * iWcount;
1678    
1679          static int32_t threshA,threshB;          static int32_t threshA,threshB;
1680          int32_t iFound,bPredEq;          int32_t iFound,bPredEq;
1681          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
1682    
1683          int32_t iSubBlock = ((y&1)<<1) + (x&1);          int32_t iSubBlock = (y & 1) + (y & 1) + (x & 1);
1684    
1685  /* Get maximum range */          MainSearch8FuncPtr MainSearchPtr;
     get_range(&min_dx, &max_dx, &min_dy, &max_dy,  
                         x, y, 8, iWidth, iHeight, iFcode);  
1686    
1687  /* we work with abs. MVs, not relative to prediction, so range is relative to 0,0 */          /* Init variables */
1688            startMV.x = start_x;
1689            startMV.y = start_y;
1690    
1691          if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))          /* Get maximum range */
1692          { min_dx = EVEN(min_dx);          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 8, iWidth, iHeight,
1693                              iFcode);
1694    
1695            if (!(MotionFlags & PMV_HALFPELDIAMOND8)) {
1696                    min_dx = EVEN(min_dx);
1697            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
1698            min_dy = EVEN(min_dy);            min_dy = EVEN(min_dy);
1699            max_dy = EVEN(max_dy);            max_dy = EVEN(max_dy);
1700          }               /* because we might use IF (dx>max_dx) THEN dx=max_dx; */          }
   
1701    
1702            /* because we might use IF (dx>max_dx) THEN dx=max_dx; */
1703          bPredEq  = get_pmvdata(pMBs, (x>>1), (y>>1), iWcount, iSubBlock, pmv, psad);          bPredEq  = get_pmvdata(pMBs, (x>>1), (y>>1), iWcount, iSubBlock, pmv, psad);
1704            // bPredEq = get_pmvdata2(pMBs, iWcount, 0, (x >> 1), (y >> 1), iSubBlock, pmv, psad);
1705    
1706          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
1707                  threshA =  512/4;                  threshA =  512/4;
1708                  threshB = 1024/4;                  threshB = 1024/4;
1709    
1710          }          } else {
         else  
         {  
1711                  threshA = psad[0]/4;                    /* good estimate */                  threshA = psad[0]/4;                    /* good estimate */
1712                  threshB = threshA+256/4;                  threshB = threshA+256/4;
1713                  if (threshA< 512/4) threshA =  512/4;                  if (threshA < 512 / 4)
1714                  if (threshA>1024/4) threshA = 1024/4;                          threshA = 512 / 4;
1715                  if (threshB>1792/4) threshB = 1792/4;                  if (threshA > 1024 / 4)
1716                            threshA = 1024 / 4;
1717                    if (threshB > 1792 / 4)
1718                            threshB = 1792 / 4;
1719          }          }
1720    
1721          iFound=0;          iFound=0;
1722    
1723  /* Step 2: Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion  /* Step 4: Calculate SAD around the Median prediction.
1724       MinSAD=SAD
1725       If Motion Vector equal to Previous frame motion vector
1726       and MinSAD<PrevFrmSAD goto Step 10.
1727       If SAD<=256 goto Step 10.
1728    */
1729    
1730    
1731    // Prepare for main loop
1732    
1733    //  if (MotionFlags & PMV_USESQUARES8)
1734    //      MainSearchPtr = Square8_MainSearch;
1735    //  else
1736    
1737            if (MotionFlags & PMV_ADVANCEDDIAMOND8)
1738                    MainSearchPtr = AdvDiamond8_MainSearch;
1739            else
1740                    MainSearchPtr = Diamond8_MainSearch;
1741    
1742    
1743            *currMV = startMV;
1744    
1745            iMinSAD =
1746                    sad8(cur,
1747                             get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
1748                                                    iEdgedWidth), iEdgedWidth);
1749            iMinSAD +=
1750                    calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y,
1751                                             (uint8_t) iFcode, iQuant);
1752    
1753            if ((iMinSAD < 256 / 4) || ((MVequal(*currMV, prevMB->mvs[iSubBlock]))
1754                                                                    && ((uint32_t) iMinSAD <
1755                                                                            prevMB->sad8[iSubBlock]))) {
1756                    if (MotionFlags & PMV_QUICKSTOP16)
1757                            goto PMVfast8_Terminate_without_Refine;
1758                    if (MotionFlags & PMV_EARLYSTOP16)
1759                            goto PMVfast8_Terminate_with_Refine;
1760            }
1761    
1762    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
1763          vector of the median.          vector of the median.
1764          If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2          If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1765  */  */
1766    
1767          if ((bPredEq) && (MVequal(pmv[0],pMB->mvs[iSubBlock]) ) )          if ((bPredEq) && (MVequal(pmv[0], prevMB->mvs[iSubBlock])))
1768                  iFound=2;                  iFound=2;
1769    
1770  /* 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.
1771          Otherwise select large Diamond Search.          Otherwise select large Diamond Search.
1772  */  */
1773    
1774          if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536/4) || (bPredEq) )          if ((!MVzero(pmv[0])) || (threshB < 1536 / 4) || (bPredEq))
1775                  iDiamondSize=1; // 1 halfpel!                  iDiamondSize=1; // 1 halfpel!
1776          else          else
1777                  iDiamondSize=2; // 2 halfpel = 1 full pixel!                  iDiamondSize=2; // 2 halfpel = 1 full pixel!
# Line 1053  Line 1779 
1779          if (!(MotionFlags & PMV_HALFPELDIAMOND8) )          if (!(MotionFlags & PMV_HALFPELDIAMOND8) )
1780                  iDiamondSize*=2;                  iDiamondSize*=2;
1781    
 /* 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;  
                 }  
1782    
1783  /*  /*
1784  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.
1785          Also calculate (0,0) but do not subtract offset.          Also calculate (0,0) but do not subtract offset.
1786          Let MinSAD be the smallest SAD up to this point.          Let MinSAD be the smallest SAD up to this point.
1787          If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
1788  */  */
1789    
1790  // the prediction might be even better than mv16  // the median prediction might be even better than mv16
1791    
1792            if (!MVequal(pmv[0], startMV))
1793          CHECK_MV8_CANDIDATE(pmv[0].x,pmv[0].y);          CHECK_MV8_CANDIDATE(pmv[0].x,pmv[0].y);
1794    
1795  // (0,0) is always possible  // (0,0) if needed
1796            if (!MVzero(pmv[0]))
1797                    if (!MVzero(startMV))
1798          CHECK_MV8_ZERO;          CHECK_MV8_ZERO;
1799    
1800  // previous frame MV is always possible  // previous frame MV if needed
1801          CHECK_MV8_CANDIDATE(pMB->mvs[iSubBlock].x,pMB->mvs[iSubBlock].y);          if (!MVzero(prevMB->mvs[iSubBlock]))
1802                    if (!MVequal(prevMB->mvs[iSubBlock], startMV))
1803                            if (!MVequal(prevMB->mvs[iSubBlock], pmv[0]))
1804                                    CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,
1805                                                                            prevMB->mvs[iSubBlock].y);
1806    
1807            if ((iMinSAD <= threshA) ||
1808                    (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
1809                     ((uint32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
1810                    if (MotionFlags & PMV_QUICKSTOP16)
1811                            goto PMVfast8_Terminate_without_Refine;
1812                    if (MotionFlags & PMV_EARLYSTOP16)
1813                            goto PMVfast8_Terminate_with_Refine;
1814            }
1815    
1816  // left neighbour, if allowed  // left neighbour, if allowed and needed
1817          if (psad[1] != MV_MAX_ERROR)          if (!MVzero(pmv[1]))
1818          {                  if (!MVequal(pmv[1], startMV))
1819                  if (!(MotionFlags & PMV_HALFPEL8 ))                          if (!MVequal(pmv[1], prevMB->mvs[iSubBlock]))
1820                  {       pmv[1].x = EVEN(pmv[1].x);                                  if (!MVequal(pmv[1], pmv[0])) {
1821                                            if (!(MotionFlags & PMV_HALFPEL8)) {
1822                                                    pmv[1].x = EVEN(pmv[1].x);
1823                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
1824                  }                  }
1825                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
1826          }          }
1827    // top neighbour, if allowed and needed
1828  // top neighbour, if allowed          if (!MVzero(pmv[2]))
1829          if (psad[2] != MV_MAX_ERROR)                  if (!MVequal(pmv[2], startMV))
1830          {                          if (!MVequal(pmv[2], prevMB->mvs[iSubBlock]))
1831                  if (!(MotionFlags & PMV_HALFPEL8 ))                                  if (!MVequal(pmv[2], pmv[0]))
1832                  {       pmv[2].x = EVEN(pmv[2].x);                                          if (!MVequal(pmv[2], pmv[1])) {
1833                                                    if (!(MotionFlags & PMV_HALFPEL8)) {
1834                                                            pmv[2].x = EVEN(pmv[2].x);
1835                          pmv[2].y = EVEN(pmv[2].y);                          pmv[2].y = EVEN(pmv[2].y);
1836                  }                  }
1837                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
1838    
1839  // top right neighbour, if allowed  // top right neighbour, if allowed and needed
1840                  if (psad[3] != MV_MAX_ERROR)                                                  if (!MVzero(pmv[3]))
1841                  {                                                          if (!MVequal(pmv[3], startMV))
1842                  if (!(MotionFlags & PMV_HALFPEL8 ))                                                                  if (!MVequal(pmv[3], prevMB->mvs[iSubBlock]))
1843                  {       pmv[3].x = EVEN(pmv[3].x);                                                                          if (!MVequal(pmv[3], pmv[0]))
1844                                                                                    if (!MVequal(pmv[3], pmv[1]))
1845                                                                                            if (!MVequal(pmv[3], pmv[2])) {
1846                                                                                                    if (!
1847                                                                                                            (MotionFlags &
1848                                                                                                             PMV_HALFPEL8)) {
1849                                                                                                            pmv[3].x = EVEN(pmv[3].x);
1850                          pmv[3].y = EVEN(pmv[3].y);                          pmv[3].y = EVEN(pmv[3].y);
1851                  }                  }
1852                          CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                                  CHECK_MV8_CANDIDATE(pmv[3].x,
1853                                                                                                                                            pmv[3].y);
1854                  }                  }
1855          }          }
1856    
1857            if ((MVzero(*currMV)) &&
1858                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1859                    iMinSAD -= MV8_00_BIAS;
1860    
1861    
1862  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
1863     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.
1864  */  */
1865    
1866          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[iSubBlock]) && (iMinSAD < pMB->sad8[iSubBlock]) ) )          if ((iMinSAD <= threshA) ||
1867                  {                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
1868                          if (MotionFlags & PMV_QUICKSTOP8)                   ((uint32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
1869                                  goto step10_8b;                  if (MotionFlags & PMV_QUICKSTOP16)
1870                          if (MotionFlags & PMV_EARLYSTOP8)                          goto PMVfast8_Terminate_without_Refine;
1871                                  goto step10_8;                  if (MotionFlags & PMV_EARLYSTOP16)
1872                            goto PMVfast8_Terminate_with_Refine;
1873                  }                  }
1874    
1875  /************ (Diamond Search)  **************/  /************ (Diamond Search)  **************/
# Line 1150  Line 1885 
1885          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1886    
1887  /* 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 */
1888          iSAD = PMVfastSearch8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
1889                  x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
1890                  currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx,
1891                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
1892                                                      iQuant, iFound);
1893    
1894          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
1895                  *currMV = newMV;                  *currMV = newMV;
1896                  iMinSAD = iSAD;                  iMinSAD = iSAD;
1897          }          }
1898    
1899          if (MotionFlags & PMV_EXTSEARCH8)          if (MotionFlags & PMV_EXTSEARCH8) {
         {  
1900  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1901    
1902                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
1903                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1904                                  x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1905                          pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, pmv,
1906                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1907                                                                      iDiamondSize, iFcode, iQuant, iFound);
1908    
1909                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
1910                                  *currMV = newMV;                                  *currMV = newMV;
1911                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
1912                          }                          }
1913                  }                  }
1914    
1915                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
1916                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1917                                  x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
1918                          0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy,
1919                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
1920                                                                      iQuant, iFound);
1921    
1922                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
1923                                  *currMV = newMV;                                  *currMV = newMV;
1924                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
1925                          }                          }
# Line 1196  Line 1930 
1930           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.
1931  */  */
1932    
1933  step10_8:    PMVfast8_Terminate_with_Refine:
1934          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
1935                  iMinSAD = PMVfastSearch8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
1936                                  x, y,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
1937                                  currMV, iMinSAD,                                                          iMinSAD, pmv, min_dx, max_dx, min_dy, max_dy,
1938                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
1939    
1940    
1941      PMVfast8_Terminate_without_Refine:
1942            currPMV->x = currMV->x - pmv[0].x;
1943            currPMV->y = currMV->y - pmv[0].y;
1944    
1945            return iMinSAD;
1946    }
1947    
1948    int32_t
1949    EPZSSearch16(const uint8_t * const pRef,
1950                             const uint8_t * const pRefH,
1951                             const uint8_t * const pRefV,
1952                             const uint8_t * const pRefHV,
1953                             const IMAGE * const pCur,
1954                             const int x,
1955                             const int y,
1956                             const uint32_t MotionFlags,
1957                             const uint32_t iQuant,
1958                             const uint32_t iFcode,
1959                             const MBParam * const pParam,
1960                             const MACROBLOCK * const pMBs,
1961                             const MACROBLOCK * const prevMBs,
1962                             VECTOR * const currMV,
1963                             VECTOR * const currPMV)
1964    {
1965            const uint32_t iWcount = pParam->mb_width;
1966            const uint32_t iHcount = pParam->mb_height;
1967    
1968            const int32_t iWidth = pParam->width;
1969            const int32_t iHeight = pParam->height;
1970            const int32_t iEdgedWidth = pParam->edged_width;
1971    
1972            const uint8_t *cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;
1973    
1974            int32_t min_dx;
1975            int32_t max_dx;
1976            int32_t min_dy;
1977            int32_t max_dy;
1978    
1979            VECTOR newMV;
1980            VECTOR backupMV;
1981    
1982            VECTOR pmv[4];
1983            int32_t psad[8];
1984    
1985            static MACROBLOCK *oldMBs = NULL;
1986    
1987    //  const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
1988            const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
1989            MACROBLOCK *oldMB = NULL;
1990    
1991            static int32_t thresh2;
1992            int32_t bPredEq;
1993            int32_t iMinSAD, iSAD = 9999;
1994    
1995            MainSearch16FuncPtr MainSearchPtr;
1996    
1997            if (oldMBs == NULL) {
1998                    oldMBs = (MACROBLOCK *) calloc(iWcount * iHcount, sizeof(MACROBLOCK));
1999    //      fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));
2000            }
2001            oldMB = oldMBs + x + y * iWcount;
2002    
2003    /* Get maximum range */
2004            get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
2005                              iFcode);
2006    
2007            if (!(MotionFlags & PMV_HALFPEL16)) {
2008                    min_dx = EVEN(min_dx);
2009                    max_dx = EVEN(max_dx);
2010                    min_dy = EVEN(min_dy);
2011                    max_dy = EVEN(max_dy);
2012            }
2013            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2014            bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
2015            // bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
2016    
2017    /* Step 4: Calculate SAD around the Median prediction.
2018            MinSAD=SAD
2019            If Motion Vector equal to Previous frame motion vector
2020                    and MinSAD<PrevFrmSAD goto Step 10.
2021            If SAD<=256 goto Step 10.
2022    */
2023    
2024    // Prepare for main loop
2025    
2026            *currMV = pmv[0];                       /* current best := median prediction */
2027            if (!(MotionFlags & PMV_HALFPEL16)) {
2028                    currMV->x = EVEN(currMV->x);
2029                    currMV->y = EVEN(currMV->y);
2030            }
2031    
2032            if (currMV->x > max_dx)
2033                    currMV->x = max_dx;
2034            if (currMV->x < min_dx)
2035                    currMV->x = min_dx;
2036            if (currMV->y > max_dy)
2037                    currMV->y = max_dy;
2038            if (currMV->y < min_dy)
2039                    currMV->y = min_dy;
2040    
2041    /***************** This is predictor SET A: only median prediction ******************/
2042    
2043            iMinSAD =
2044                    sad16(cur,
2045                              get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
2046                                                     iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
2047            iMinSAD +=
2048                    calc_delta_16(currMV->x - pmv[0].x, currMV->y - pmv[0].y,
2049                                              (uint8_t) iFcode, iQuant);
2050    
2051    // thresh1 is fixed to 256
2052            if ((iMinSAD < 256) ||
2053                    ((MVequal(*currMV, prevMB->mvs[0])) &&
2054                     ((uint32_t) iMinSAD < prevMB->sad16))) {
2055                    if (MotionFlags & PMV_QUICKSTOP16)
2056                            goto EPZS16_Terminate_without_Refine;
2057                    if (MotionFlags & PMV_EARLYSTOP16)
2058                            goto EPZS16_Terminate_with_Refine;
2059            }
2060    
2061    /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
2062    
2063    // previous frame MV
2064            CHECK_MV16_CANDIDATE(prevMB->mvs[0].x, prevMB->mvs[0].y);
2065    
2066  step10_8b:  // set threshhold based on Min of Prediction and SAD of collocated block
2067    // CHECK_MV16 always uses iSAD for the SAD of last vector to check, so now iSAD is what we want
2068    
2069            if ((x == 0) && (y == 0)) {
2070                    thresh2 = 512;
2071            } else {
2072    /* T_k = 1.2 * MIN(SAD_top,SAD_left,SAD_topleft,SAD_coll) +128;   [Tourapis, 2002] */
2073    
2074                    thresh2 = MIN(psad[0], iSAD) * 6 / 5 + 128;
2075            }
2076    
2077    // MV=(0,0) is often a good choice
2078    
2079            CHECK_MV16_ZERO;
2080    
2081    
2082    // left neighbour, if allowed
2083            if (x != 0) {
2084                    if (!(MotionFlags & PMV_HALFPEL16)) {
2085                            pmv[1].x = EVEN(pmv[1].x);
2086                            pmv[1].y = EVEN(pmv[1].y);
2087                    }
2088                    CHECK_MV16_CANDIDATE(pmv[1].x, pmv[1].y);
2089            }
2090    // top neighbour, if allowed
2091            if (y != 0) {
2092                    if (!(MotionFlags & PMV_HALFPEL16)) {
2093                            pmv[2].x = EVEN(pmv[2].x);
2094                            pmv[2].y = EVEN(pmv[2].y);
2095                    }
2096                    CHECK_MV16_CANDIDATE(pmv[2].x, pmv[2].y);
2097    
2098    // top right neighbour, if allowed
2099                    if ((uint32_t) x != (iWcount - 1)) {
2100                            if (!(MotionFlags & PMV_HALFPEL16)) {
2101                                    pmv[3].x = EVEN(pmv[3].x);
2102                                    pmv[3].y = EVEN(pmv[3].y);
2103                            }
2104                            CHECK_MV16_CANDIDATE(pmv[3].x, pmv[3].y);
2105                    }
2106            }
2107    
2108    /* Terminate if MinSAD <= T_2
2109       Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
2110    */
2111    
2112            if ((iMinSAD <= thresh2)
2113                    || (MVequal(*currMV, prevMB->mvs[0]) &&
2114                            ((uint32_t) iMinSAD <= prevMB->sad16))) {
2115                    if (MotionFlags & PMV_QUICKSTOP16)
2116                            goto EPZS16_Terminate_without_Refine;
2117                    if (MotionFlags & PMV_EARLYSTOP16)
2118                            goto EPZS16_Terminate_with_Refine;
2119            }
2120    
2121    /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/
2122    
2123            backupMV = prevMB->mvs[0];      // collocated MV
2124            backupMV.x += (prevMB->mvs[0].x - oldMB->mvs[0].x);     // acceleration X
2125            backupMV.y += (prevMB->mvs[0].y - oldMB->mvs[0].y);     // acceleration Y
2126    
2127            CHECK_MV16_CANDIDATE(backupMV.x, backupMV.y);
2128    
2129    // left neighbour
2130            if (x != 0)
2131                    CHECK_MV16_CANDIDATE((prevMB - 1)->mvs[0].x, (prevMB - 1)->mvs[0].y);
2132    
2133    // top neighbour
2134            if (y != 0)
2135                    CHECK_MV16_CANDIDATE((prevMB - iWcount)->mvs[0].x,
2136                                                             (prevMB - iWcount)->mvs[0].y);
2137    
2138    // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs
2139    
2140            if ((uint32_t) x != iWcount - 1)
2141                    CHECK_MV16_CANDIDATE((prevMB + 1)->mvs[0].x, (prevMB + 1)->mvs[0].y);
2142    
2143    // bottom neighbour, dito
2144            if ((uint32_t) y != iHcount - 1)
2145                    CHECK_MV16_CANDIDATE((prevMB + iWcount)->mvs[0].x,
2146                                                             (prevMB + iWcount)->mvs[0].y);
2147    
2148    /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */
2149            if (iMinSAD <= thresh2) {
2150                    if (MotionFlags & PMV_QUICKSTOP16)
2151                            goto EPZS16_Terminate_without_Refine;
2152                    if (MotionFlags & PMV_EARLYSTOP16)
2153                            goto EPZS16_Terminate_with_Refine;
2154            }
2155    
2156    /************ (if Diamond Search)  **************/
2157    
2158            backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
2159    
2160            if (MotionFlags & PMV_USESQUARES8)
2161                    MainSearchPtr = Square16_MainSearch;
2162            else
2163             if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2164                    MainSearchPtr = AdvDiamond16_MainSearch;
2165            else
2166                    MainSearchPtr = Diamond16_MainSearch;
2167    
2168    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
2169    
2170            iSAD =
2171                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2172                                                      currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx,
2173                                                      min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2174    
2175            if (iSAD < iMinSAD) {
2176                    *currMV = newMV;
2177                    iMinSAD = iSAD;
2178            }
2179    
2180    
2181            if (MotionFlags & PMV_EXTSEARCH16) {
2182    /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
2183    
2184                    if (!(MVequal(pmv[0], backupMV))) {
2185                            iSAD =
2186                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2187                                                                      pmv[0].x, pmv[0].y, iMinSAD, &newMV, pmv,
2188                                                                      min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2189                                                                      2, iFcode, iQuant, 0);
2190                    }
2191    
2192                    if (iSAD < iMinSAD) {
2193                            *currMV = newMV;
2194                            iMinSAD = iSAD;
2195                    }
2196    
2197                    if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2198                            iSAD =
2199                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2200                                                                      iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy,
2201                                                                      max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2202    
2203                            if (iSAD < iMinSAD) {
2204                                    *currMV = newMV;
2205                                    iMinSAD = iSAD;
2206                            }
2207                    }
2208            }
2209    
2210    /***************        Choose best MV found     **************/
2211    
2212      EPZS16_Terminate_with_Refine:
2213            if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step
2214                    iMinSAD =
2215                            Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2216                                                             iMinSAD, pmv, min_dx, max_dx, min_dy, max_dy,
2217                                                             iFcode, iQuant, iEdgedWidth);
2218    
2219      EPZS16_Terminate_without_Refine:
2220    
2221            *oldMB = *prevMB;
2222    
2223          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - pmv[0].x;
2224          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - pmv[0].y;
2225            return iMinSAD;
2226    }
2227    
2228    
2229    int32_t
2230    EPZSSearch8(const uint8_t * const pRef,
2231                            const uint8_t * const pRefH,
2232                            const uint8_t * const pRefV,
2233                            const uint8_t * const pRefHV,
2234                            const IMAGE * const pCur,
2235                            const int x,
2236                            const int y,
2237                            const int start_x,
2238                            const int start_y,
2239                            const uint32_t MotionFlags,
2240                            const uint32_t iQuant,
2241                            const uint32_t iFcode,
2242                            const MBParam * const pParam,
2243                            const MACROBLOCK * const pMBs,
2244                            const MACROBLOCK * const prevMBs,
2245                            VECTOR * const currMV,
2246                            VECTOR * const currPMV)
2247    {
2248    /* Please not that EPZS might not be a good choice for 8x8-block motion search ! */
2249    
2250            const uint32_t iWcount = pParam->mb_width;
2251            const int32_t iWidth = pParam->width;
2252            const int32_t iHeight = pParam->height;
2253            const int32_t iEdgedWidth = pParam->edged_width;
2254    
2255            const uint8_t *cur = pCur->y + x * 8 + y * 8 * iEdgedWidth;
2256    
2257            int32_t iDiamondSize = 1;
2258    
2259            int32_t min_dx;
2260            int32_t max_dx;
2261            int32_t min_dy;
2262            int32_t max_dy;
2263    
2264            VECTOR newMV;
2265            VECTOR backupMV;
2266    
2267            VECTOR pmv[4];
2268            int32_t psad[8];
2269    
2270            const int32_t iSubBlock = ((y & 1) << 1) + (x & 1);
2271    
2272    //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
2273            const MACROBLOCK *const prevMB = prevMBs + (x >> 1) + (y >> 1) * iWcount;
2274    
2275            int32_t bPredEq;
2276            int32_t iMinSAD, iSAD = 9999;
2277    
2278            MainSearch8FuncPtr MainSearchPtr;
2279    
2280    /* Get maximum range */
2281            get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 8, iWidth, iHeight,
2282                              iFcode);
2283    
2284    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
2285    
2286            if (!(MotionFlags & PMV_HALFPEL8)) {
2287                    min_dx = EVEN(min_dx);
2288                    max_dx = EVEN(max_dx);
2289                    min_dy = EVEN(min_dy);
2290                    max_dy = EVEN(max_dy);
2291            }
2292            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2293            bPredEq = get_pmvdata(pMBs, x >> 1, y >> 1, iWcount, iSubBlock, pmv, psad);
2294            // bPredEq = get_pmvdata2(pMBs, iWcount, 0, x >> 1, y >> 1, iSubBlock, pmv, psad);
2295    
2296    
2297    /* Step 4: Calculate SAD around the Median prediction.
2298            MinSAD=SAD
2299            If Motion Vector equal to Previous frame motion vector
2300                    and MinSAD<PrevFrmSAD goto Step 10.
2301            If SAD<=256 goto Step 10.
2302    */
2303    
2304    // Prepare for main loop
2305    
2306    
2307            if (!(MotionFlags & PMV_HALFPEL8)) {
2308                    currMV->x = EVEN(currMV->x);
2309                    currMV->y = EVEN(currMV->y);
2310            }
2311    
2312            if (currMV->x > max_dx)
2313                    currMV->x = max_dx;
2314            if (currMV->x < min_dx)
2315                    currMV->x = min_dx;
2316            if (currMV->y > max_dy)
2317                    currMV->y = max_dy;
2318            if (currMV->y < min_dy)
2319                    currMV->y = min_dy;
2320    
2321    /***************** This is predictor SET A: only median prediction ******************/
2322    
2323    
2324            iMinSAD =
2325                    sad8(cur,
2326                             get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
2327                                                    iEdgedWidth), iEdgedWidth);
2328            iMinSAD +=
2329                    calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y,
2330                                             (uint8_t) iFcode, iQuant);
2331    
2332    
2333    // thresh1 is fixed to 256
2334            if (iMinSAD < 256 / 4) {
2335                    if (MotionFlags & PMV_QUICKSTOP8)
2336                            goto EPZS8_Terminate_without_Refine;
2337                    if (MotionFlags & PMV_EARLYSTOP8)
2338                            goto EPZS8_Terminate_with_Refine;
2339            }
2340    
2341    /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
2342    
2343    
2344    // MV=(0,0) is often a good choice
2345            CHECK_MV8_ZERO;
2346    
2347    // previous frame MV
2348            CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x, prevMB->mvs[iSubBlock].y);
2349    
2350    // left neighbour, if allowed
2351            if (psad[1] != MV_MAX_ERROR) {
2352                    if (!(MotionFlags & PMV_HALFPEL8)) {
2353                            pmv[1].x = EVEN(pmv[1].x);
2354                            pmv[1].y = EVEN(pmv[1].y);
2355                    }
2356                    CHECK_MV8_CANDIDATE(pmv[1].x, pmv[1].y);
2357            }
2358    // top neighbour, if allowed
2359            if (psad[2] != MV_MAX_ERROR) {
2360                    if (!(MotionFlags & PMV_HALFPEL8)) {
2361                            pmv[2].x = EVEN(pmv[2].x);
2362                            pmv[2].y = EVEN(pmv[2].y);
2363                    }
2364                    CHECK_MV8_CANDIDATE(pmv[2].x, pmv[2].y);
2365    
2366    // top right neighbour, if allowed
2367                    if (psad[3] != MV_MAX_ERROR) {
2368                            if (!(MotionFlags & PMV_HALFPEL8)) {
2369                                    pmv[3].x = EVEN(pmv[3].x);
2370                                    pmv[3].y = EVEN(pmv[3].y);
2371                            }
2372                            CHECK_MV8_CANDIDATE(pmv[3].x, pmv[3].y);
2373                    }
2374            }
2375    
2376    /*  // this bias is zero anyway, at the moment!
2377    
2378            if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) ) // && (iMinSAD <= iQuant * 96)
2379                    iMinSAD -= MV8_00_BIAS;
2380    
2381    */
2382    
2383    /* Terminate if MinSAD <= T_2
2384       Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
2385    */
2386    
2387            if (iMinSAD < 512 / 4) {        /* T_2 == 512/4 hardcoded */
2388                    if (MotionFlags & PMV_QUICKSTOP8)
2389                            goto EPZS8_Terminate_without_Refine;
2390                    if (MotionFlags & PMV_EARLYSTOP8)
2391                            goto EPZS8_Terminate_with_Refine;
2392            }
2393    
2394    /************ (Diamond Search)  **************/
2395    
2396            backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
2397    
2398            if (!(MotionFlags & PMV_HALFPELDIAMOND8))
2399                    iDiamondSize *= 2;
2400    
2401    /* default: use best prediction as starting point for one call of EPZS_MainSearch */
2402    
2403    // there is no EPZS^2 for inter4v at the moment
2404    
2405    //  if (MotionFlags & PMV_USESQUARES8)
2406    //      MainSearchPtr = Square8_MainSearch;
2407    //  else
2408    
2409            if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2410                    MainSearchPtr = AdvDiamond8_MainSearch;
2411            else
2412                    MainSearchPtr = Diamond8_MainSearch;
2413    
2414            iSAD =
2415                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2416                                                      currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx,
2417                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2418                                                      iQuant, 0);
2419    
2420    
2421            if (iSAD < iMinSAD) {
2422                    *currMV = newMV;
2423                    iMinSAD = iSAD;
2424            }
2425    
2426            if (MotionFlags & PMV_EXTSEARCH8) {
2427    /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
2428    
2429                    if (!(MVequal(pmv[0], backupMV))) {
2430                            iSAD =
2431                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2432                                                                      pmv[0].x, pmv[0].y, iMinSAD, &newMV, pmv,
2433                                                                      min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2434                                                                      iDiamondSize, iFcode, iQuant, 0);
2435    
2436                            if (iSAD < iMinSAD) {
2437                                    *currMV = newMV;
2438                                    iMinSAD = iSAD;
2439                            }
2440                    }
2441    
2442                    if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2443                            iSAD =
2444                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2445                                                                      iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy,
2446                                                                      max_dy, iEdgedWidth, iDiamondSize, iFcode,
2447                                                                      iQuant, 0);
2448    
2449                            if (iSAD < iMinSAD) {
2450                                    *currMV = newMV;
2451                                    iMinSAD = iSAD;
2452                            }
2453                    }
2454            }
2455    
2456    /***************        Choose best MV found     **************/
2457    
2458      EPZS8_Terminate_with_Refine:
2459            if (MotionFlags & PMV_HALFPELREFINE8)   // perform final half-pel step
2460                    iMinSAD =
2461                            Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2462                                                            iMinSAD, pmv, min_dx, max_dx, min_dy, max_dy,
2463                                                            iFcode, iQuant, iEdgedWidth);
2464    
2465      EPZS8_Terminate_without_Refine:
2466    
2467            currPMV->x = currMV->x - pmv[0].x;
2468            currPMV->y = currMV->y - pmv[0].y;
2469          return iMinSAD;          return iMinSAD;
2470  }  }
2471    
2472    
2473    
2474    
2475    
2476    /* ***********************************************************
2477            bvop motion estimation
2478    // TODO: need to incorporate prediction here (eg. sad += calc_delta_16)
2479    ***************************************************************/
2480    
2481    
2482    void
2483    MotionEstimationBVOP(MBParam * const pParam,
2484                                             FRAMEINFO * const frame,
2485                                             // forward (past) reference
2486                                             const MACROBLOCK * const f_mbs,
2487                                             const IMAGE * const f_ref,
2488                                             const IMAGE * const f_refH,
2489                                             const IMAGE * const f_refV,
2490                                             const IMAGE * const f_refHV,
2491                                             // backward (future) reference
2492                                             const MACROBLOCK * const b_mbs,
2493                                             const IMAGE * const b_ref,
2494                                             const IMAGE * const b_refH,
2495                                             const IMAGE * const b_refV,
2496                                             const IMAGE * const b_refHV)
2497    {
2498            const uint32_t mb_width = pParam->mb_width;
2499            const uint32_t mb_height = pParam->mb_height;
2500            const int32_t edged_width = pParam->edged_width;
2501    
2502            uint32_t i, j;
2503    
2504            int32_t f_sad16;
2505            int32_t b_sad16;
2506            int32_t i_sad16;
2507            int32_t d_sad16;
2508            int32_t best_sad;
2509    
2510            VECTOR pmv_dontcare;
2511    
2512            // note: i==horizontal, j==vertical
2513            for (j = 0; j < mb_height; j++) {
2514                    for (i = 0; i < mb_width; i++) {
2515                            MACROBLOCK *mb = &frame->mbs[i + j * mb_width];
2516                            const MACROBLOCK *f_mb = &f_mbs[i + j * mb_width];
2517                            const MACROBLOCK *b_mb = &b_mbs[i + j * mb_width];
2518    
2519                            if (b_mb->mode == MODE_INTER && b_mb->cbp == 0 &&
2520                                    b_mb->mvs[0].x == 0 && b_mb->mvs[0].y == 0) {
2521                                    mb->mode = MODE_NOT_CODED;
2522                                    mb->mvs[0].x = 0;
2523                                    mb->mvs[0].y = 0;
2524                                    mb->b_mvs[0].x = 0;
2525                                    mb->b_mvs[0].y = 0;
2526                                    continue;
2527                            }
2528                    /* force F_SAD16
2529                            f_sad16 = 100;
2530                            b_sad16 = 65535;
2531    
2532                            mb->mode = MODE_FORWARD;
2533                            mb->mvs[0].x = 1;
2534                            mb->mvs[0].y = 1;
2535                            mb->b_mvs[0].x = 1;
2536                            mb->b_mvs[0].y = 1;
2537                            continue;
2538                     ^^ force F_SAD16 */
2539    
2540    
2541                            // forward search
2542                            f_sad16 =
2543                                    SEARCH16(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2544                                                     &frame->image, i, j, frame->motion_flags,
2545                                                     frame->quant, frame->fcode, pParam,
2546                                                     f_mbs,  f_mbs, /* todo */
2547                                                     &mb->mvs[0], &pmv_dontcare);   // ignore pmv
2548    
2549                            // backward search
2550                            b_sad16 = SEARCH16(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
2551                                                    &frame->image, i, j, frame->motion_flags,
2552                                                    frame->quant, frame->bcode, pParam,
2553                                                    b_mbs, b_mbs,   /* todo */
2554                                                    &mb->b_mvs[0], &pmv_dontcare);  // ignore pmv
2555    
2556                            // interpolate search (simple, but effective)
2557                            i_sad16 = 65535;
2558    
2559                            /*
2560                            x/y range somewhat buggy
2561                            i_sad16 =
2562                                    sad16bi_c(frame->image.y + i * 16 + j * 16 * edged_width,
2563                                                      get_ref(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2564                                                                      i, j, 16, mb->mvs[0].x, mb->mvs[0].y,
2565                                                                      edged_width), get_ref(b_ref->y, b_refH->y,
2566                                                                                                                    b_refV->y, b_refHV->y,
2567                                                                                                                    i, j, 16,
2568                                                                                                                    mb->b_mvs[0].x,
2569                                                                                                                    mb->b_mvs[0].x,
2570                                                                                                                    edged_width),
2571                                                      edged_width);
2572                            */
2573    
2574                            // TODO: direct search
2575                            // predictor + range of [-32,32]
2576                            d_sad16 = 65535;
2577    
2578    
2579                            if (f_sad16 < b_sad16) {
2580                                    best_sad = f_sad16;
2581                                    mb->mode = MODE_FORWARD;
2582                            } else {
2583                                    best_sad = b_sad16;
2584                                    mb->mode = MODE_BACKWARD;
2585                            }
2586    
2587                            if (i_sad16 < best_sad) {
2588                                    best_sad = i_sad16;
2589                                    mb->mode = MODE_INTERPOLATE;
2590                            }
2591    
2592                            if (d_sad16 < best_sad) {
2593                                    best_sad = d_sad16;
2594                                    mb->mode = MODE_DIRECT;
2595                            }
2596    
2597                    }
2598            }
2599    }

Legend:
Removed from v.3  
changed lines
  Added in v.254

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