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

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

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

revision 78, Thu Mar 28 20:57:25 2002 UTC revision 174, Sat May 11 23:54:30 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 8
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(
83                                            const uint8_t * const pRef,
84                                            const uint8_t * const pRefH,
85                                            const uint8_t * const pRefV,
86                                            const uint8_t * const pRefHV,
87                                            const IMAGE * const pCur,
88                                            const int x, 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(
99  #define MAX(X, Y) ((X)>(Y)?(X):(Y))                                          const uint8_t * const pRef,
100  #define ABS(X)    (((X)>0)?(X):-(X))                                          const uint8_t * const pRefH,
101  #define SIGN(X)   (((X)>0)?1:-1)                                          const uint8_t * const pRefV,
102                                            const uint8_t * const pRefHV,
103                                            const IMAGE * const pCur,
104                                            const int x, 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(
# Line 78  Line 119 
119          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
120          const IMAGE * const pCur,          const IMAGE * const pCur,
121          const int x, const int y,          const int x, const int y,
122          const int start_x, int start_y,                                          const int start_x, const int start_y,
123          const uint32_t iQuality,                                          const uint32_t MotionFlags,
124          MBParam * const pParam,                                          const uint32_t iQuant,
125          MACROBLOCK * const pMBs,                                          const uint32_t iFcode,
126                                            const MBParam * const pParam,
127                                            const MACROBLOCK * const pMBs,
128                                            const MACROBLOCK * const prevMBs,
129          VECTOR * const currMV,          VECTOR * const currMV,
130          VECTOR * const currPMV);          VECTOR * const currPMV);
131    
132  int32_t PMVfastSearch16(  int32_t EPZSSearch8(
133          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, const int y,
139          const uint32_t iQuality,                                          const int start_x, const int start_y,
140          MBParam * const pParam,                                          const uint32_t MotionFlags,
141          MACROBLOCK * const pMBs,                                          const uint32_t iQuant,
142                                            const uint32_t iFcode,
143                                            const MBParam * const pParam,
144                                            const MACROBLOCK * const pMBs,
145                                            const MACROBLOCK * const prevMBs,
146          VECTOR * const currMV,          VECTOR * const currMV,
147          VECTOR * const currPMV);          VECTOR * const currPMV);
148    
149    
150    typedef int32_t (MainSearch16Func)(
151            const uint8_t * const pRef,
152            const uint8_t * const pRefH,
153            const uint8_t * const pRefV,
154            const uint8_t * const pRefHV,
155            const uint8_t * const cur,
156            const int x, const int y,
157            int32_t startx, int32_t starty,
158            int32_t iMinSAD,
159            VECTOR * const currMV,
160            const VECTOR * const pmv,
161            const int32_t min_dx, const int32_t max_dx,
162            const int32_t min_dy, const int32_t max_dy,
163            const int32_t iEdgedWidth,
164            const int32_t iDiamondSize,
165            const int32_t iFcode,
166            const int32_t iQuant,
167            int iFound);
168    
169    typedef MainSearch16Func* MainSearch16FuncPtr;
170    
 /*  
  * diamond search stuff  
  * keep the the sequence in circular order (so optimization works)  
  */  
171    
172  typedef struct  typedef int32_t (MainSearch8Func)(
173  {          const uint8_t * const pRef,
174          int32_t dx;          const uint8_t * const pRefH,
175          int32_t dy;          const uint8_t * const pRefV,
176  }          const uint8_t * const pRefHV,
177  DPOINT;          const uint8_t * const cur,
178            const int x, const int y,
179            int32_t startx, int32_t starty,
180            int32_t iMinSAD,
181            VECTOR * const currMV,
182            const VECTOR * const pmv,
183            const int32_t min_dx, const int32_t max_dx,
184            const int32_t min_dy, const int32_t max_dy,
185            const int32_t iEdgedWidth,
186            const int32_t iDiamondSize,
187            const int32_t iFcode,
188            const int32_t iQuant,
189            int iFound);
190    
191    typedef MainSearch8Func* MainSearch8FuncPtr;
192    
193  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 */
194  {          {     0    ,(int)(1.00235+0.5), (int)(1.15582+0.5), (int)(1.31976+0.5), (int)(1.49591+0.5), (int)(1.68601+0.5),
195          {0, 1}, {1, 0}, {0, -1}, {-1, 0}          (int)(1.89187+0.5), (int)(2.11542+0.5), (int)(2.35878+0.5), (int)(2.62429+0.5), (int)(2.91455+0.5),
196  };          (int)(3.23253+0.5), (int)(3.58158+0.5), (int)(3.96555+0.5), (int)(4.38887+0.5), (int)(4.85673+0.5),
197            (int)(5.37519+0.5), (int)(5.95144+0.5), (int)(6.59408+0.5), (int)(7.31349+0.5), (int)(8.12242+0.5),
198            (int)(9.03669+0.5), (int)(10.0763+0.5), (int)(11.2669+0.5), (int)(12.6426+0.5), (int)(14.2493+0.5),
199            (int)(16.1512+0.5), (int)(18.442+0.5),  (int)(21.2656+0.5), (int)(24.8580+0.5), (int)(29.6436+0.5),
200            (int)(36.4949+0.5)      };
201    
202    static int32_t *lambda_vec8 = lambda_vec16;     /* same table for INTER and INTER4V for now*/
203    
 static const DPOINT diamond_large[8] =  
 {  
         {0, 2}, {1, 1}, {2, 0}, {1, -1}, {0, -2}, {-1, -1}, {-2, 0}, {-1, 1}  
 };  
204    
205    
206  // mv.length table  // mv.length table
# Line 160  Line 238 
238  }  }
239    
240    
241  static __inline uint32_t calc_delta_16(const int32_t dx, const int32_t dy, const uint32_t iFcode)  static __inline uint32_t calc_delta_16(const int32_t dx, const int32_t dy, const uint32_t iFcode, const uint32_t iQuant)
 {  
         return NEIGH_TEND_16X16 * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));  
 }  
   
 static __inline uint32_t calc_delta_8(const int32_t dx, const int32_t dy, const uint32_t iFcode)  
   
242  {  {
243      return NEIGH_TEND_8X8 * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));          return NEIGH_TEND_16X16 * lambda_vec16[iQuant] * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));
244  }  }
245    
246    static __inline uint32_t calc_delta_8(const int32_t dx, const int32_t dy, const uint32_t iFcode, const uint32_t iQuant)
247    
   
   
 /* calculate the min/max range (in halfpixels)  
         relative to the _MACROBLOCK_ position  
 */  
   
 static void __inline get_range(  
         int32_t * const min_dx, int32_t * const max_dx,  
         int32_t * const min_dy, int32_t * const max_dy,  
         const uint32_t x, const uint32_t y,  
         const uint32_t block_sz,                                        // block dimension, 8 or 16  
         const uint32_t width, const uint32_t height,  
         const uint32_t fcode)  
248  {  {
249        return NEIGH_TEND_8X8 * lambda_vec8[iQuant] * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));
         const int search_range = 32 << (fcode - 1);  
         const int high = search_range - 1;  
         const int low = -search_range;  
   
         // convert full-pixel measurements to half pixel  
         const int hp_width = 2 * width;  
         const int hp_height = 2 * height;  
         const int hp_edge = 2 * block_sz;  
         const int hp_x = 2 * (x) * block_sz;            // we need _right end_ of block, not x-coordinate  
         const int hp_y = 2 * (y) * block_sz;            // same for _bottom end_  
   
         *max_dx = MIN(high,     hp_width - hp_x);  
         *max_dy = MIN(high,     hp_height - hp_y);  
         *min_dx = MAX(low,      -(hp_edge + hp_x));  
         *min_dy = MAX(low,      -(hp_edge + hp_y));  
   
 }  
   
   
 /*  
  * getref: calculate reference image pointer  
  * the decision to use interpolation h/v/hv or the normal image is  
  * based on dx & dy.  
  */  
   
 static __inline const uint8_t * get_ref(  
         const uint8_t * const refn,  
         const uint8_t * const refh,  
         const uint8_t * const refv,  
         const uint8_t * const refhv,  
         const uint32_t x, const uint32_t y,  
         const uint32_t block,                                   // block dimension, 8 or 16  
         const int32_t dx, const int32_t dy,  
         const uint32_t stride)  
 {  
   
         switch ( ((dx&1)<<1) + (dy&1) )         // ((dx%2)?2:0)+((dy%2)?1:0)  
         {  
         case 0  : return refn + (x*block+dx/2) + (y*block+dy/2)*stride;  
         case 1  : return refv + (x*block+dx/2) + (y*block+(dy-1)/2)*stride;  
         case 2  : return refh + (x*block+(dx-1)/2) + (y*block+dy/2)*stride;  
         default :  
         case 3  : return refhv + (x*block+(dx-1)/2) + (y*block+(dy-1)/2)*stride;  
         }  
   
250  }  }
251    
252    
 /* This is somehow a copy of get_ref, but with MV instead of X,Y */  
   
 static __inline const uint8_t * get_ref_mv(  
         const uint8_t * const refn,  
         const uint8_t * const refh,  
         const uint8_t * const refv,  
         const uint8_t * const refhv,  
         const uint32_t x, const uint32_t y,  
         const uint32_t block,                   // block dimension, 8 or 16  
         const VECTOR* mv,       // measured in half-pel!  
         const uint32_t stride)  
 {  
253    
         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;  
         }  
254    
 }  
255    
256  #ifndef SEARCH16  #ifndef SEARCH16
257  #define SEARCH16        PMVfastSearch16  #define SEARCH16        PMVfastSearch16
258    //#define SEARCH16      FullSearch16
259    //#define SEARCH16      EPZSSearch16
260  #endif  #endif
261    
262  #ifndef SEARCH8  #ifndef SEARCH8
263  #define SEARCH8         PMVfastSearch8  #define SEARCH8         PMVfastSearch8
264    //#define SEARCH8       EPZSSearch8
265  #endif  #endif
266    
267  bool MotionEstimation(  bool MotionEstimation(
         MACROBLOCK * const pMBs,  
268          MBParam * const pParam,          MBParam * const pParam,
269          const IMAGE * const pRef,          FRAMEINFO * const current,
270            FRAMEINFO * const reference,
271          const IMAGE * const pRefH,          const IMAGE * const pRefH,
272          const IMAGE * const pRefV,          const IMAGE * const pRefV,
273          const IMAGE * const pRefHV,          const IMAGE * const pRefHV,
         IMAGE * const pCurrent,  
274          const uint32_t iLimit)          const uint32_t iLimit)
275    
276  {  {
277          const uint32_t iWcount = pParam->mb_width;          const uint32_t iWcount = pParam->mb_width;
278          const uint32_t iHcount = pParam->mb_height;          const uint32_t iHcount = pParam->mb_height;
279            MACROBLOCK * const pMBs = current->mbs;
280            MACROBLOCK * const prevMBs = reference->mbs;    // previous frame
281    
282          uint32_t i, j, iIntra = 0;          const IMAGE * const pCurrent = &current->image;
283            const IMAGE * const pRef = &reference->image;
284    
285          VECTOR mv16;          const VECTOR zeroMV = {0,0};
         VECTOR pmv16;  
286    
287          int32_t sad8 = 0;          int32_t x, y;
288          int32_t sad16;          int32_t iIntra = 0;
289          int32_t deviation;          VECTOR pmv;
290    
291          // note: i==horizontal, j==vertical          if (sadInit)
292          for (i = 0; i < iHcount; i++)                  (*sadInit)();
                 for (j = 0; j < iWcount; j++)  
                 {  
                         MACROBLOCK *pMB = &pMBs[j + i * iWcount];  
293    
294                          sad16 = SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,          for (y = 0; y < iHcount; y++)
295                                           j, i, pParam->motion_flags,                  for (x = 0; x < iWcount; x++)
296                                           pParam, pMBs, &mv16, &pmv16);                  {
297                          pMB->sad16=sad16;                          MACROBLOCK* const pMB = &pMBs[x + y * iWcount];
298    
299                            pMB->sad16 = SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
300                                             x, y, current->motion_flags, current->quant, current->fcode,
301                                             pParam, pMBs, prevMBs, &pMB->mv16, &pMB->pmvs[0]);
302                    }
303    
304                          /* decide: MODE_INTER or MODE_INTRA          for (y = 0; y < iHcount; y++)
305                             if (dev_intra < sad_inter - 2 * nb) use_intra                  for (x = 0; x < iWcount; x++)
306                          */                  {
307                            MACROBLOCK* const pMB = &pMBs[x + y * iWcount];
308    
309                          deviation = dev16(pCurrent->y + j*16 + i*16*pParam->edged_width, pParam->edged_width);                          if (0 < (pMB->sad16 - MV16_INTER_BIAS))
310                            {
311                                    int32_t deviation;
312                                    deviation = dev16(pCurrent->y + x*16 + y*16*pParam->edged_width,
313                                                             pParam->edged_width);
314    
315                          if (deviation < (sad16 - INTER_BIAS))                                  if (deviation < (pMB->sad16 - MV16_INTER_BIAS))
316                          {                          {
317                                  pMB->mode = MODE_INTRA;                                  pMB->mode = MODE_INTRA;
318                                  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]
319                                  pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = 0;                                                                   = pMB->mvs[2] = pMB->mvs[3] = zeroMV;
320                                            pMB->sad16 = pMB->sad8[0] = pMB->sad8[1]
321                                                                 = pMB->sad8[2] = pMB->sad8[3] = 0;
322    
323                                  iIntra++;                                  iIntra++;
324                                  if(iIntra >= iLimit)                                  if(iIntra >= iLimit)
# Line 320  Line 326 
326    
327                                  continue;                                  continue;
328                          }                          }
   
                         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];  
329                          }                          }
330    
331                            if ( (current->global_flags & XVID_INTER4V)
332                                    && (!(current->global_flags & XVID_LUMIMASKING)
333                                            || pMB->dquant == NO_CHANGE) )
334                            {
335                                    int32_t neigh=0;
336    
337                                    if (x>0)
338                                    {       neigh += abs((pMB->mv16.x)-((pMB-1)->mv16.x));
339                                            neigh += abs((pMB->mv16.y)-((pMB-1)->mv16.y));
340                                    }
341                                    if (y>0)
342                                    {       neigh += abs((pMB->mv16.x)-((pMB-iWcount)->mv16.x));
343                                            neigh += abs((pMB->mv16.y)-((pMB-iWcount)->mv16.y));
344                                    }
345                                    if (x<(iWcount-1))
346                                    {       neigh += abs((pMB->mv16.x)-((pMB+1)->mv16.x));
347                                            neigh += abs((pMB->mv16.y)-((pMB+1)->mv16.y));
348                                    }
349                                    if (y<(iHcount-1))
350                                    {       neigh += abs((pMB->mv16.x)-((pMB+iHcount)->mv16.x));
351                                            neigh += abs((pMB->mv16.y)-((pMB+iHcount)->mv16.y));
352                                    }
353    
354                                    if (neigh > NEIGH_MOVE_THRESH)
355                                    {
356                                            int32_t sad8 = 129; //IMV16X16 * current->quant;
357    
358                                    if (sad8 < pMB->sad16)
359                                    sad8 += pMB->sad8[0]
360                                            = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
361                                                           2*x, 2*y, pMB->mv16.x, pMB->mv16.y,
362                                                               current->motion_flags, current->quant, current->fcode,
363                                                           pParam, pMBs, prevMBs, &pMB->mvs[0], &pMB->pmvs[0]);
364    
365                                    if (sad8 < pMB->sad16)
366                                    sad8 += pMB->sad8[1]
367                                            = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
368                                   2*x+1, 2*y, pMB->mv16.x, pMB->mv16.y,
369                                                    current->motion_flags, current->quant, current->fcode,
370                                                    pParam, pMBs, prevMBs, &pMB->mvs[1], &pMB->pmvs[1]);
371    
372                                    if (sad8 < pMB->sad16)
373                                    sad8 += pMB->sad8[2]
374                                            = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
375                                                    2*x, 2*y+1, pMB->mv16.x, pMB->mv16.y,
376                                                    current->motion_flags, current->quant, current->fcode,
377                                                    pParam, pMBs, prevMBs, &pMB->mvs[2], &pMB->pmvs[2]);
378    
379                                    if (sad8 < pMB->sad16)
380                                    sad8 += pMB->sad8[3]
381                                            = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
382                                                    2*x+1, 2*y+1, pMB->mv16.x, pMB->mv16.y,
383                                                    current->motion_flags, current->quant, current->fcode,
384                                                    pParam, pMBs, prevMBs, &pMB->mvs[3], &pMB->pmvs[3]);
385    
386                          /* decide: MODE_INTER or MODE_INTER4V                          /* decide: MODE_INTER or MODE_INTER4V
387                             mpeg4:   if (sad8 < sad16 - nb/2+1) use_inter4v                             mpeg4:   if (sad8 < pMB->sad16 - nb/2+1) use_inter4v
388                          */                          */
389    
390                          if (pMB->dquant == NO_CHANGE) {                                  if (sad8 < pMB->sad16)
391                                  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  
392                                          pMB->mode = MODE_INTER4V;                                          pMB->mode = MODE_INTER4V;
393                   pMB->sad8[0] *= 4;
394                                            pMB->sad8[1] *= 4;
395                                            pMB->sad8[2] *= 4;
396                                            pMB->sad8[3] *= 4;
397                                            continue;
398                          }                          }
                         else  
                         {  
                                 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;  
399                          }                          }
400                  }                  }
401    
402          return 0;                          pMB->mode = MODE_INTER;
403  }                          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mv16;
404             pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = pMB->sad16;
405    
406  #define MVzero(A) ( ((A).x)==(0) && ((A).y)==(0) )                          pmv = get_pmv(pMBs, x, y, pParam->mb_width, 0);
407                            // get_pmv has to be called again.
408                            // intra-decision and inter4v change predictors
409    
410  #define MVequal(A,B) ( ((A).x)==((B).x) && ((A).y)==((B).y) )                                  pMB->pmvs[0].x = pMB->mv16.x - pmv.x;
411                                    pMB->pmvs[0].y = pMB->mv16.y - pmv.y;
412                    }
413    
414            return 0;
415    }
416    
417  #define CHECK_MV16_ZERO {\  #define CHECK_MV16_ZERO {\
418    if ( (0 <= max_dx) && (0 >= min_dx) \    if ( (0 <= max_dx) && (0 >= min_dx) \
419      && (0 <= max_dy) && (0 >= min_dy) ) \      && (0 <= max_dy) && (0 >= min_dy) ) \
420    { \    { \
421      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0, 0 , iEdgedWidth), iEdgedWidth, MV_MAX_ERROR); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0, 0 , iEdgedWidth), iEdgedWidth, MV_MAX_ERROR); \
422      iSAD += calc_delta_16(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode, iQuant);\
     if (iSAD <= iQuant * 96)    \  
         iSAD -= MV16_00_BIAS; \  
423      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
424      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \
425  }  }
426    
427    #define NOCHECK_MV16_CANDIDATE(X,Y) { \
428        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
429        iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\
430        if (iSAD < iMinSAD) \
431        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
432    }
433    
434  #define CHECK_MV16_CANDIDATE(X,Y) { \  #define CHECK_MV16_CANDIDATE(X,Y) { \
435    if ( ((X) <= max_dx) && ((X) >= min_dx) \    if ( ((X) <= max_dx) && ((X) >= min_dx) \
436      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
437    { \    { \
438      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
439      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\
440      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
441      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
442  }  }
# Line 408  Line 446 
446      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
447    { \    { \
448      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
449      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\
450      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
451      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
452  }  }
# Line 418  Line 456 
456      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
457    { \    { \
458      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
459      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\
460      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
461      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
462  }  }
# Line 426  Line 464 
464    
465  #define CHECK_MV8_ZERO {\  #define CHECK_MV8_ZERO {\
466    iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, 0, 0 , iEdgedWidth), iEdgedWidth); \    iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, 0, 0 , iEdgedWidth), iEdgedWidth); \
467    iSAD += calc_delta_8(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode) * iQuant;\    iSAD += calc_delta_8(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode, iQuant);\
468    if (iSAD < iMinSAD) \    if (iSAD < iMinSAD) \
469    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \
470  }  }
471    
472    #define NOCHECK_MV8_CANDIDATE(X,Y) \
473      { \
474        iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
475        iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\
476        if (iSAD < iMinSAD) \
477        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
478    }
479    
480  #define CHECK_MV8_CANDIDATE(X,Y) { \  #define CHECK_MV8_CANDIDATE(X,Y) { \
481    if ( ((X) <= max_dx) && ((X) >= min_dx) \    if ( ((X) <= max_dx) && ((X) >= min_dx) \
482      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
483    { \    { \
484      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
485      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\
486      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
487      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
488  }  }
# Line 447  Line 492 
492      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
493    { \    { \
494      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
495      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\
496      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
497      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
498  }  }
# Line 457  Line 502 
502      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
503    { \    { \
504      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
505      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\
506      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
507      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
508  }  }
# Line 472  Line 517 
517                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
518                                          const int x, const int y,                                          const int x, const int y,
519                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
520                                            const uint32_t iQuant,
521                                            const uint32_t iFcode,
522                                          MBParam * const pParam,                                          MBParam * const pParam,
523                                          MACROBLOCK * const pMBs,                                          const MACROBLOCK * const pMBs,
524                                            const MACROBLOCK * const prevMBs,
525                                          VECTOR * const currMV,                                          VECTOR * const currMV,
526                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
527  {  {
528          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
         const int32_t iQuant = pParam->quant;  
529          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
530          int32_t iSAD;          int32_t iSAD;
531          int32_t pred_x,pred_y;          int32_t pred_x,pred_y;
# Line 501  Line 548 
548  }  }
549  */  */
550    
551  int32_t PMVfastSearch16_MainSearch(  int32_t Diamond16_MainSearch(
552          const uint8_t * const pRef,          const uint8_t * const pRef,
553          const uint8_t * const pRefH,          const uint8_t * const pRefH,
554          const uint8_t * const pRefV,          const uint8_t * const pRefV,
# Line 558  Line 605 
605          return iMinSAD;          return iMinSAD;
606  }  }
607    
608  int32_t PMVfastSearch16_Refine(  int32_t Square16_MainSearch(
609          const uint8_t * const pRef,          const uint8_t * const pRef,
610          const uint8_t * const pRefH,          const uint8_t * const pRefH,
611          const uint8_t * const pRefV,          const uint8_t * const pRefV,
612          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
613          const uint8_t * const cur,          const uint8_t * const cur,
614          const int x, const int y,          const int x, const int y,
615          VECTOR * const currMV,                                          int32_t startx, int32_t starty,
616          int32_t iMinSAD,          int32_t iMinSAD,
617                                            VECTOR * const currMV,
618          const VECTOR * const pmv,          const VECTOR * const pmv,
619          const int32_t min_dx, const int32_t max_dx,          const int32_t min_dx, const int32_t max_dx,
620          const int32_t min_dy, const int32_t max_dy,          const int32_t min_dy, const int32_t max_dy,
621                                            const int32_t iEdgedWidth,
622                                            const int32_t iDiamondSize,
623          const int32_t iFcode,          const int32_t iFcode,
624          const int32_t iQuant,          const int32_t iQuant,
625          const int32_t iEdgedWidth)                                          int iFound)
626  {  {
627  /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */  /* Do a square search around given starting point, return SAD of best */
628    
629            int32_t iDirection=0;
630          int32_t iSAD;          int32_t iSAD;
631          VECTOR backupMV = *currMV;          VECTOR backupMV;
632            backupMV.x = startx;
633          CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y-1);          backupMV.y = starty;
         CHECK_MV16_CANDIDATE(backupMV.x  ,backupMV.y-1);  
         CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y-1);  
         CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y);  
         CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y);  
         CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y+1);  
         CHECK_MV16_CANDIDATE(backupMV.x  ,backupMV.y+1);  
         CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y+1);  
   
         return iMinSAD;  
 }  
   
 #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)  
634    
635  int32_t PMVfastSearch16(  /* It's one search with full square pattern, and new parts for all following diamonds */
         const uint8_t * const pRef,  
         const uint8_t * const pRefH,  
         const uint8_t * const pRefV,  
         const uint8_t * const pRefHV,  
         const IMAGE * const pCur,  
         const int x, const int y,  
         const uint32_t MotionFlags,  
         MBParam * const pParam,  
         MACROBLOCK * const pMBs,  
         VECTOR * const currMV,  
         VECTOR * const currPMV)  
 {  
         const uint32_t iWcount = pParam->mb_width;  
         const int32_t iFcode = pParam->fixed_code;  
         const int32_t iQuant = pParam->quant;  
         const int32_t iWidth = pParam->width;  
         const int32_t iHeight = pParam->height;  
         const int32_t iEdgedWidth = pParam->edged_width;  
636    
637          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;  /*   new direction are extra, so 1-4 is normal diamond
638          537
639          1*2
640          648
641    */
642    
643          int32_t iDiamondSize;          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
644            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
645            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
646            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
647    
648          int32_t min_dx;          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
649          int32_t max_dx;          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
650          int32_t min_dy;          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
651          int32_t max_dy;          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
652    
         int32_t iFound;  
653    
654          VECTOR newMV;          if (iDirection)
655          VECTOR backupMV;        /* just for PMVFAST */                  while (!iFound)
656                    {
657                            iFound = 1;
658                            backupMV=*currMV;
659    
660          VECTOR pmv[4];                          switch (iDirection)
661          int32_t psad[4];                          {
662                                    case 1:
663                                            CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);
664                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
665                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
666                                            break;
667                                    case 2:
668                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
669                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
670                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
671                                            break;
672    
673          MACROBLOCK * const pMB = pMBs + x + y * iWcount;                                  case 3:
674                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
675                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
676                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
677                                            break;
678    
679          static int32_t threshA,threshB;                                  case 4:
680          int32_t bPredEq;                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
681          int32_t iMinSAD,iSAD;                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
682                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
683                                            break;
684    
685  /* Get maximum range */                                  case 5:
686          get_range(&min_dx, &max_dx, &min_dy, &max_dy,                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
687                    x, y, 16, iWidth, iHeight, iFcode);                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
688                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
689                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
690                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
691                                            break;
692    
693  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */                                  case 6:
694                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
695                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
696    
697          if (!(MotionFlags & PMV_HALFPEL16 ))                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
698          { min_dx = EVEN(min_dx);                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
699          max_dx = EVEN(max_dx);                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
         min_dy = EVEN(min_dy);  
         max_dy = EVEN(max_dy);  
         }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */  
700    
701                                            break;
702    
703          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);                                  case 7:
704                                            CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);
705                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
706                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
707                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
708                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
709                                            break;
710    
711          if ((x==0) && (y==0) )                                  case 8:
712          {                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
713                  threshA =  512;                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
714                  threshB = 1024;                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
715                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
716                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
717                                            break;
718                            default:
719                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
720                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
721                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
722                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
723    
724                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
725                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
726                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
727                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
728                                            break;
729                            }
730          }          }
731          else          else
732          {          {
733                  threshA = psad[0];                          currMV->x = startx;
734                  threshB = threshA+256;                          currMV->y = starty;
735                  if (threshA< 512) threshA =  512;                  }
736                  if (threshA>1024) threshA = 1024;          return iMinSAD;
                 if (threshB>1792) threshB = 1792;  
737          }          }
738    
         iFound=0;  
   
 /* Step 2: Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion  
    vector of the median.  
    If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2  
 */  
   
         if ((bPredEq) && (MVequal(pmv[0],pMB->mvs[0]) ) )  
                 iFound=2;  
   
 /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.  
    Otherwise select large Diamond Search.  
 */  
739    
740          if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536) || (bPredEq) )  int32_t Full16_MainSearch(
741                  iDiamondSize=1; // halfpel!                                          const uint8_t * const pRef,
742          else                                          const uint8_t * const pRefH,
743                  iDiamondSize=2; // halfpel!                                          const uint8_t * const pRefV,
744                                            const uint8_t * const pRefHV,
745                                            const uint8_t * const cur,
746                                            const int x, const int y,
747                                            int32_t startx, int32_t starty,
748                                            int32_t iMinSAD,
749                                            VECTOR * const currMV,
750                                            const VECTOR * const pmv,
751                                            const int32_t min_dx, const int32_t max_dx,
752                                            const int32_t min_dy, const int32_t max_dy,
753                                            const int32_t iEdgedWidth,
754                                            const int32_t iDiamondSize,
755                                            const int32_t iFcode,
756                                            const int32_t iQuant,
757                                            int iFound)
758    {
759            int32_t iSAD;
760            int32_t dx,dy;
761            VECTOR backupMV;
762            backupMV.x = startx;
763            backupMV.y = starty;
764    
765          if (!(MotionFlags & PMV_HALFPELDIAMOND16) )          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
766                  iDiamondSize*=2;                  for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
767                            NOCHECK_MV16_CANDIDATE(dx,dy);
768    
769            return iMinSAD;
770    }
771    
772    int32_t Full8_MainSearch(
773                                            const uint8_t * const pRef,
774                                            const uint8_t * const pRefH,
775                                            const uint8_t * const pRefV,
776                                            const uint8_t * const pRefHV,
777                                            const uint8_t * const cur,
778                                            const int x, const int y,
779                                            int32_t startx, int32_t starty,
780                                            int32_t iMinSAD,
781                                            VECTOR * const currMV,
782                                            const VECTOR * const pmv,
783                                            const int32_t min_dx, const int32_t max_dx,
784                                            const int32_t min_dy, const int32_t max_dy,
785                                            const int32_t iEdgedWidth,
786                                            const int32_t iDiamondSize,
787                                            const int32_t iFcode,
788                                            const int32_t iQuant,
789                                            int iFound)
790    {
791            int32_t iSAD;
792            int32_t dx,dy;
793            VECTOR backupMV;
794            backupMV.x = startx;
795            backupMV.y = starty;
796    
797            for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
798                    for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
799                            NOCHECK_MV8_CANDIDATE(dx,dy);
800    
801            return iMinSAD;
802    }
803    
804    
805    
806    int32_t Halfpel16_Refine(
807            const uint8_t * const pRef,
808            const uint8_t * const pRefH,
809            const uint8_t * const pRefV,
810            const uint8_t * const pRefHV,
811            const uint8_t * const cur,
812            const int x, const int y,
813            VECTOR * const currMV,
814            int32_t iMinSAD,
815            const VECTOR * const pmv,
816            const int32_t min_dx, const int32_t max_dx,
817            const int32_t min_dy, const int32_t max_dy,
818            const int32_t iFcode,
819            const int32_t iQuant,
820            const int32_t iEdgedWidth)
821    {
822    /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */
823    
824            int32_t iSAD;
825            VECTOR backupMV = *currMV;
826    
827            CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y-1);
828            CHECK_MV16_CANDIDATE(backupMV.x  ,backupMV.y-1);
829            CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y-1);
830            CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y);
831            CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y);
832            CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y+1);
833            CHECK_MV16_CANDIDATE(backupMV.x  ,backupMV.y+1);
834            CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y+1);
835    
836            return iMinSAD;
837    }
838    
839    #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
840    
841    
842    int32_t PMVfastSearch16(
843                                            const uint8_t * const pRef,
844                                            const uint8_t * const pRefH,
845                                            const uint8_t * const pRefV,
846                                            const uint8_t * const pRefHV,
847                                            const IMAGE * const pCur,
848                                            const int x, const int y,
849                                            const uint32_t MotionFlags,
850                                            const uint32_t iQuant,
851                                            const uint32_t iFcode,
852                                            const MBParam * const pParam,
853                                            const MACROBLOCK * const pMBs,
854                                            const MACROBLOCK * const prevMBs,
855                                            VECTOR * const currMV,
856                                            VECTOR * const currPMV)
857    {
858        const uint32_t iWcount = pParam->mb_width;
859            const int32_t iWidth = pParam->width;
860            const int32_t iHeight = pParam->height;
861            const int32_t iEdgedWidth = pParam->edged_width;
862    
863            const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
864    
865            int32_t iDiamondSize;
866    
867            int32_t min_dx;
868            int32_t max_dx;
869            int32_t min_dy;
870            int32_t max_dy;
871    
872            int32_t iFound;
873    
874            VECTOR newMV;
875            VECTOR backupMV;        /* just for PMVFAST */
876    
877            VECTOR pmv[4];
878            int32_t psad[4];
879    
880    //      const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
881            const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
882    
883            static int32_t threshA,threshB;
884            int32_t bPredEq;
885            int32_t iMinSAD,iSAD;
886    
887    /* Get maximum range */
888            get_range(&min_dx, &max_dx, &min_dy, &max_dy,
889                      x, y, 16, iWidth, iHeight, iFcode);
890    
891    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
892    
893            if (!(MotionFlags & PMV_HALFPEL16 ))
894            { min_dx = EVEN(min_dx);
895            max_dx = EVEN(max_dx);
896            min_dy = EVEN(min_dy);
897            max_dy = EVEN(max_dy);
898            }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
899    
900    
901            bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
902    
903            if ((x==0) && (y==0) )
904            {
905                    threshA =  512;
906                    threshB = 1024;
907    
908            }
909            else
910            {
911                    threshA = psad[0];
912                    threshB = threshA+256;
913                    if (threshA< 512) threshA =  512;
914                    if (threshA>1024) threshA = 1024;
915                    if (threshB>1792) threshB = 1792;
916            }
917    
918            iFound=0;
919    
920  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
921     MinSAD=SAD     MinSAD=SAD
# Line 696  Line 924 
924     If SAD<=256 goto Step 10.     If SAD<=256 goto Step 10.
925  */  */
926    
   
 // Prepare for main loop  
   
927          *currMV=pmv[0];         /* current best := prediction */          *currMV=pmv[0];         /* current best := prediction */
928          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16 ))
929          {       /* This should NOT be necessary! */          {       /* This should NOT be necessary! */
# Line 726  Line 951 
951          iMinSAD = sad16( cur,          iMinSAD = sad16( cur,
952                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),
953                           iEdgedWidth, MV_MAX_ERROR);                           iEdgedWidth, MV_MAX_ERROR);
954          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);
955    
956          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && (iMinSAD < pMB->sad16) ) )          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )
957            {
958                    if (iMinSAD < 2*iQuant) // high chances for SKIP-mode
959                    {
960                            if (!MVzero(*currMV))
961          {          {
962                                    iMinSAD += MV16_00_BIAS;
963                                    CHECK_MV16_ZERO;                // (0,0) saves space for letterboxed pictures
964                                    iMinSAD -= MV16_00_BIAS;
965                            }
966                    }
967    
968                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
969                          goto step10b;                          goto PMVfast16_Terminate_without_Refine;
970                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
971                          goto step10;                          goto PMVfast16_Terminate_with_Refine;
972          }          }
973    
974    
975    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
976       vector of the median.
977       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
978    */
979    
980            if ((bPredEq) && (MVequal(pmv[0],prevMB->mvs[0]) ) )
981                    iFound=2;
982    
983    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
984       Otherwise select large Diamond Search.
985    */
986    
987            if ( (!MVzero(pmv[0])) || (threshB<1536) || (bPredEq) )
988                    iDiamondSize=1; // halfpel!
989            else
990                    iDiamondSize=2; // halfpel!
991    
992            if (!(MotionFlags & PMV_HALFPELDIAMOND16) )
993                    iDiamondSize*=2;
994    
995  /*  /*
996     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.
997     Also calculate (0,0) but do not subtract offset.     Also calculate (0,0) but do not subtract offset.
998     Let MinSAD be the smallest SAD up to this point.     Let MinSAD be the smallest SAD up to this point.
999     If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
1000  */  */
1001    
1002  // (0,0) is always possible  // (0,0) is always possible
1003    
1004            if (!MVzero(pmv[0]))
1005          CHECK_MV16_ZERO;          CHECK_MV16_ZERO;
1006    
1007  // previous frame MV is always possible  // previous frame MV is always possible
1008          CHECK_MV16_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);  
1009            if (!MVzero(prevMB->mvs[0]))
1010            if (!MVequal(prevMB->mvs[0],pmv[0]))
1011                    CHECK_MV16_CANDIDATE(prevMB->mvs[0].x,prevMB->mvs[0].y);
1012    
1013  // left neighbour, if allowed  // left neighbour, if allowed
1014          if (x != 0)  
1015            if (!MVzero(pmv[1]))
1016            if (!MVequal(pmv[1],prevMB->mvs[0]))
1017            if (!MVequal(pmv[1],pmv[0]))
1018          {          {
1019                  if (!(MotionFlags & PMV_HALFPEL16 ))                  if (!(MotionFlags & PMV_HALFPEL16 ))
1020                  {       pmv[1].x = EVEN(pmv[1].x);                  {       pmv[1].x = EVEN(pmv[1].x);
1021                  pmv[1].y = EVEN(pmv[1].y);                  pmv[1].y = EVEN(pmv[1].y);
1022                  }                  }
1023    
1024                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1025          }          }
1026    
1027  // top neighbour, if allowed  // top neighbour, if allowed
1028          if (y != 0)          if (!MVzero(pmv[2]))
1029            if (!MVequal(pmv[2],prevMB->mvs[0]))
1030            if (!MVequal(pmv[2],pmv[0]))
1031            if (!MVequal(pmv[2],pmv[1]))
1032          {          {
1033                  if (!(MotionFlags & PMV_HALFPEL16 ))                  if (!(MotionFlags & PMV_HALFPEL16 ))
1034                  {       pmv[2].x = EVEN(pmv[2].x);                  {       pmv[2].x = EVEN(pmv[2].x);
# Line 771  Line 1037 
1037                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1038    
1039  // top right neighbour, if allowed  // top right neighbour, if allowed
1040                  if (x != (iWcount-1))                  if (!MVzero(pmv[3]))
1041                    if (!MVequal(pmv[3],prevMB->mvs[0]))
1042                    if (!MVequal(pmv[3],pmv[0]))
1043                    if (!MVequal(pmv[3],pmv[1]))
1044                    if (!MVequal(pmv[3],pmv[2]))
1045                  {                  {
1046                          if (!(MotionFlags & PMV_HALFPEL16 ))                          if (!(MotionFlags & PMV_HALFPEL16 ))
1047                          {       pmv[3].x = EVEN(pmv[3].x);                          {       pmv[3].x = EVEN(pmv[3].x);
# Line 781  Line 1051 
1051                  }                  }
1052          }          }
1053    
1054            if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96)*/ )
1055                    iMinSAD -= MV16_00_BIAS;
1056    
1057    
1058  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
1059     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.
1060  */  */
1061    
1062          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[0]) && (iMinSAD < pMB->sad16) ) )          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[0]) && ((uint32_t)iMinSAD < prevMB->sad16) ) )
1063          {          {
1064                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1065                          goto step10b;                          goto PMVfast16_Terminate_without_Refine;
1066                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
1067                          goto step10;                          goto PMVfast16_Terminate_with_Refine;
1068          }          }
1069    
1070    
# Line 807  Line 1081 
1081          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1082    
1083  /* 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 */
1084          iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1085                                            x, y,                                            x, y,
1086                                            currMV->x, currMV->y, iMinSAD, &newMV,                                            currMV->x, currMV->y, iMinSAD, &newMV,
1087                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
# Line 823  Line 1097 
1097  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1098    
1099                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0],backupMV)) )
1100                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1101                                                            x, y,                                                            x, y,
1102                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1103                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
# Line 836  Line 1110 
1110                  }                  }
1111    
1112                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1113                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1114                                                            x, y,                                                            x, y,
1115                                                            0, 0, iMinSAD, &newMV,                                                            0, 0, iMinSAD, &newMV,
1116                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
# Line 853  Line 1127 
1127     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.
1128  */  */
1129    
1130   step10:  PMVfast16_Terminate_with_Refine:
1131          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
1132                  iMinSAD = PMVfastSearch16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1133                                                    x, y,                                                    x, y,
1134                                                    currMV, iMinSAD,                                                    currMV, iMinSAD,
1135                                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1136    
1137   step10b:  PMVfast16_Terminate_without_Refine:
1138          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - pmv[0].x;
1139          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - pmv[0].y;
1140          return iMinSAD;          return iMinSAD;
# Line 871  Line 1145 
1145    
1146    
1147    
1148  int32_t PMVfastSearch8_MainSearch(  int32_t Diamond8_MainSearch(
1149          const uint8_t * const pRef,          const uint8_t * const pRef,
1150          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1151          const uint8_t * const pRefV,          const uint8_t * const pRefV,
# Line 928  Line 1202 
1202          return iMinSAD;          return iMinSAD;
1203  }  }
1204    
1205  int32_t PMVfastSearch8_Refine(  int32_t Halfpel8_Refine(
1206          const uint8_t * const pRef,          const uint8_t * const pRef,
1207          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1208          const uint8_t * const pRefV,          const uint8_t * const pRefV,
# Line 971  Line 1245 
1245          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1246          const IMAGE * const pCur,          const IMAGE * const pCur,
1247          const int x, const int y,          const int x, const int y,
1248          const int start_x, int start_y,                                          const int start_x, const int start_y,
1249          const uint32_t MotionFlags,          const uint32_t MotionFlags,
1250          MBParam * const pParam,                                          const uint32_t iQuant,
1251          MACROBLOCK * const pMBs,                                          const uint32_t iFcode,
1252                                            const MBParam * const pParam,
1253                                            const MACROBLOCK * const pMBs,
1254                                            const MACROBLOCK * const prevMBs,
1255          VECTOR * const currMV,          VECTOR * const currMV,
1256          VECTOR * const currPMV)          VECTOR * const currPMV)
1257  {  {
1258          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;  
1259          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
1260          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
1261          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
# Line 999  Line 1273 
1273          int32_t psad[4];          int32_t psad[4];
1274          VECTOR newMV;          VECTOR newMV;
1275          VECTOR backupMV;          VECTOR backupMV;
1276            VECTOR startMV;
1277    
1278          MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;  //      const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1279            const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;
1280    
1281          static int32_t threshA,threshB;          static int32_t threshA,threshB;
1282          int32_t iFound,bPredEq;          int32_t iFound,bPredEq;
1283          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
1284    
1285          int32_t iSubBlock = ((y&1)<<1) + (x&1);          int32_t iSubBlock = (y&1)+(y&1) + (x&1);
1286    
1287            /* Init variables */
1288            startMV.x = start_x;
1289            startMV.y = start_y;
1290    
1291  /* Get maximum range */  /* Get maximum range */
1292          get_range(&min_dx, &max_dx, &min_dy, &max_dy,          get_range(&min_dx, &max_dx, &min_dy, &max_dy,
1293                    x, y, 8, iWidth, iHeight, iFcode);                    x, y, 8, iWidth, iHeight, iFcode);
1294    
 /* we work with abs. MVs, not relative to prediction, so range is relative to 0,0 */  
   
1295          if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))          if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))
1296          { min_dx = EVEN(min_dx);          { min_dx = EVEN(min_dx);
1297          max_dx = EVEN(max_dx);          max_dx = EVEN(max_dx);
# Line 1041  Line 1319 
1319    
1320          iFound=0;          iFound=0;
1321    
 /* Step 2: Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion  
    vector of the median.  
    If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2  
 */  
   
         if ((bPredEq) && (MVequal(pmv[0],pMB->mvs[iSubBlock]) ) )  
                 iFound=2;  
   
 /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.  
    Otherwise select large Diamond Search.  
 */  
   
         if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536/4) || (bPredEq) )  
                 iDiamondSize=1; // 1 halfpel!  
         else  
                 iDiamondSize=2; // 2 halfpel = 1 full pixel!  
   
         if (!(MotionFlags & PMV_HALFPELDIAMOND8) )  
                 iDiamondSize*=2;  
   
1322  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
1323     MinSAD=SAD     MinSAD=SAD
1324     If Motion Vector equal to Previous frame motion vector     If Motion Vector equal to Previous frame motion vector
# Line 1071  Line 1329 
1329    
1330  // Prepare for main loop  // Prepare for main loop
1331    
1332          currMV->x=start_x;              /* start with mv16 */          *currMV = startMV;
         currMV->y=start_y;  
1333    
1334          iMinSAD = sad8( cur,          iMinSAD = sad8( cur,
1335                          get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),                          get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),
1336                          iEdgedWidth);                          iEdgedWidth);
1337          iMinSAD += calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y, (uint8_t)iFcode) * iQuant;          iMinSAD += calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y, (uint8_t)iFcode, iQuant);
1338    
1339          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,pMB->mvs[iSubBlock])) && (iMinSAD < pMB->sad8[iSubBlock]) ) )          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,prevMB->mvs[iSubBlock]))
1340                                    && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )
1341          {          {
1342                  if (MotionFlags & PMV_QUICKSTOP8)                  if (MotionFlags & PMV_QUICKSTOP16)
1343                          goto step10_8b;                          goto PMVfast8_Terminate_without_Refine;
1344                  if (MotionFlags & PMV_EARLYSTOP8)                  if (MotionFlags & PMV_EARLYSTOP16)
1345                          goto step10_8;                          goto PMVfast8_Terminate_with_Refine;
1346          }          }
1347    
1348    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
1349       vector of the median.
1350       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1351    */
1352    
1353            if ((bPredEq) && (MVequal(pmv[0],prevMB->mvs[iSubBlock]) ) )
1354                    iFound=2;
1355    
1356    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
1357       Otherwise select large Diamond Search.
1358    */
1359    
1360            if ( (!MVzero(pmv[0])) || (threshB<1536/4) || (bPredEq) )
1361                    iDiamondSize=1; // 1 halfpel!
1362            else
1363                    iDiamondSize=2; // 2 halfpel = 1 full pixel!
1364    
1365            if (!(MotionFlags & PMV_HALFPELDIAMOND8) )
1366                    iDiamondSize*=2;
1367    
1368    
1369  /*  /*
1370     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.
1371     Also calculate (0,0) but do not subtract offset.     Also calculate (0,0) but do not subtract offset.
1372     Let MinSAD be the smallest SAD up to this point.     Let MinSAD be the smallest SAD up to this point.
1373     If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
1374  */  */
1375    
1376  // the prediction might be even better than mv16  // the median prediction might be even better than mv16
1377    
1378            if (!MVequal(pmv[0],startMV))
1379          CHECK_MV8_CANDIDATE(pmv[0].x,pmv[0].y);          CHECK_MV8_CANDIDATE(pmv[0].x,pmv[0].y);
1380    
1381  // (0,0) is always possible  // (0,0) if needed
1382            if (!MVzero(pmv[0]))
1383            if (!MVzero(startMV))
1384          CHECK_MV8_ZERO;          CHECK_MV8_ZERO;
1385    
1386  // previous frame MV is always possible  // previous frame MV if needed
1387          CHECK_MV8_CANDIDATE(pMB->mvs[iSubBlock].x,pMB->mvs[iSubBlock].y);          if (!MVzero(prevMB->mvs[iSubBlock]))
1388            if (!MVequal(prevMB->mvs[iSubBlock],startMV))
1389            if (!MVequal(prevMB->mvs[iSubBlock],pmv[0]))
1390            CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);
1391    
1392  // left neighbour, if allowed          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[iSubBlock]) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )
1393          if (psad[1] != MV_MAX_ERROR)          {
1394                    if (MotionFlags & PMV_QUICKSTOP16)
1395                            goto PMVfast8_Terminate_without_Refine;
1396                    if (MotionFlags & PMV_EARLYSTOP16)
1397                            goto PMVfast8_Terminate_with_Refine;
1398            }
1399    
1400    
1401    // left neighbour, if allowed and needed
1402            if (!MVzero(pmv[1]))
1403            if (!MVequal(pmv[1],startMV))
1404            if (!MVequal(pmv[1],prevMB->mvs[iSubBlock]))
1405            if (!MVequal(pmv[1],pmv[0]))
1406          {          {
1407                  if (!(MotionFlags & PMV_HALFPEL8 ))                  if (!(MotionFlags & PMV_HALFPEL8 ))
1408                  {       pmv[1].x = EVEN(pmv[1].x);                  {       pmv[1].x = EVEN(pmv[1].x);
# Line 1113  Line 1411 
1411                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
1412          }          }
1413    
1414  // top neighbour, if allowed  // top neighbour, if allowed and needed
1415          if (psad[2] != MV_MAX_ERROR)          if (!MVzero(pmv[2]))
1416            if (!MVequal(pmv[2],startMV))
1417            if (!MVequal(pmv[2],prevMB->mvs[iSubBlock]))
1418            if (!MVequal(pmv[2],pmv[0]))
1419            if (!MVequal(pmv[2],pmv[1]))
1420          {          {
1421                  if (!(MotionFlags & PMV_HALFPEL8 ))                  if (!(MotionFlags & PMV_HALFPEL8 ))
1422                  {       pmv[2].x = EVEN(pmv[2].x);                  {       pmv[2].x = EVEN(pmv[2].x);
# Line 1122  Line 1424 
1424                  }                  }
1425                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
1426    
1427  // top right neighbour, if allowed  // top right neighbour, if allowed and needed
1428                  if (psad[3] != MV_MAX_ERROR)          if (!MVzero(pmv[3]))
1429            if (!MVequal(pmv[3],startMV))
1430            if (!MVequal(pmv[3],prevMB->mvs[iSubBlock]))
1431            if (!MVequal(pmv[3],pmv[0]))
1432            if (!MVequal(pmv[3],pmv[1]))
1433            if (!MVequal(pmv[3],pmv[2]))
1434                  {                  {
1435                          if (!(MotionFlags & PMV_HALFPEL8 ))                          if (!(MotionFlags & PMV_HALFPEL8 ))
1436                          {       pmv[3].x = EVEN(pmv[3].x);                          {       pmv[3].x = EVEN(pmv[3].x);
# Line 1133  Line 1440 
1440                  }                  }
1441          }          }
1442    
1443            if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1444                    iMinSAD -= MV8_00_BIAS;
1445    
1446    
1447  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
1448     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.
1449  */  */
1450    
1451          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[iSubBlock]) && (iMinSAD < pMB->sad8[iSubBlock]) ) )          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[iSubBlock]) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )
1452          {          {
1453                  if (MotionFlags & PMV_QUICKSTOP8)                  if (MotionFlags & PMV_QUICKSTOP16)
1454                          goto step10_8b;                          goto PMVfast8_Terminate_without_Refine;
1455                  if (MotionFlags & PMV_EARLYSTOP8)                  if (MotionFlags & PMV_EARLYSTOP16)
1456                          goto step10_8;                          goto PMVfast8_Terminate_with_Refine;
1457          }          }
1458    
1459  /************ (Diamond Search)  **************/  /************ (Diamond Search)  **************/
# Line 1158  Line 1469 
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 = PMVfastSearch8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD = Diamond8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1473                                           x, y,                                           x, y,
1474                                           currMV->x, currMV->y, iMinSAD, &newMV,                                           currMV->x, currMV->y, iMinSAD, &newMV,
1475                                           pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                           pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
# Line 1174  Line 1485 
1485  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1486    
1487                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0],backupMV)) )
1488                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1489                                                            x, y,                                                            x, y,
1490                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1491                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
# Line 1187  Line 1498 
1498                  }                  }
1499    
1500                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1501                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1502                                                            x, y,                                                            x, y,
1503                                                            0, 0, iMinSAD, &newMV,                                                            0, 0, iMinSAD, &newMV,
1504                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
# Line 1204  Line 1515 
1515     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.
1516  */  */
1517    
1518   step10_8:  PMVfast8_Terminate_with_Refine:
1519          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
1520                  iMinSAD = PMVfastSearch8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1521                                                   x, y,                                                   x, y,
1522                                                   currMV, iMinSAD,                                                   currMV, iMinSAD,
1523                                                   pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                   pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1524    
  step10_8b:  
1525    
1526    PMVfast8_Terminate_without_Refine:
1527          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - pmv[0].x;
1528          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - pmv[0].y;
1529    
1530          return iMinSAD;          return iMinSAD;
1531  }  }
1532    
1533    int32_t EPZSSearch16(
1534                                            const uint8_t * const pRef,
1535                                            const uint8_t * const pRefH,
1536                                            const uint8_t * const pRefV,
1537                                            const uint8_t * const pRefHV,
1538                                            const IMAGE * const pCur,
1539                                            const int x, const int y,
1540                                            const uint32_t MotionFlags,
1541                                            const uint32_t iQuant,
1542                                            const uint32_t iFcode,
1543                                            const MBParam * const pParam,
1544                                            const MACROBLOCK * const pMBs,
1545                                            const MACROBLOCK * const prevMBs,
1546                                            VECTOR * const currMV,
1547                                            VECTOR * const currPMV)
1548    {
1549        const uint32_t iWcount = pParam->mb_width;
1550        const uint32_t iHcount = pParam->mb_height;
1551    
1552            const int32_t iWidth = pParam->width;
1553            const int32_t iHeight = pParam->height;
1554            const int32_t iEdgedWidth = pParam->edged_width;
1555    
1556            const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
1557    
1558            int32_t min_dx;
1559            int32_t max_dx;
1560            int32_t min_dy;
1561            int32_t max_dy;
1562    
1563            VECTOR newMV;
1564            VECTOR backupMV;
1565    
1566            VECTOR pmv[4];
1567            int32_t psad[8];
1568    
1569            static MACROBLOCK * oldMBs = NULL;
1570    //      const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
1571            const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
1572            MACROBLOCK * oldMB = NULL;
1573    
1574            static int32_t thresh2;
1575            int32_t bPredEq;
1576            int32_t iMinSAD,iSAD=9999;
1577    
1578            MainSearch16FuncPtr EPZSMainSearchPtr;
1579    
1580            if (oldMBs == NULL)
1581            {       oldMBs = (MACROBLOCK*) calloc(iWcount*iHcount,sizeof(MACROBLOCK));
1582    //              fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));
1583            }
1584            oldMB = oldMBs + x + y * iWcount;
1585    
1586    /* Get maximum range */
1587            get_range(&min_dx, &max_dx, &min_dy, &max_dy,
1588                            x, y, 16, iWidth, iHeight, iFcode);
1589    
1590            if (!(MotionFlags & PMV_HALFPEL16 ))
1591            { min_dx = EVEN(min_dx);
1592              max_dx = EVEN(max_dx);
1593              min_dy = EVEN(min_dy);
1594              max_dy = EVEN(max_dy);
1595            }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1596    
1597            bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
1598    
1599    /* Step 4: Calculate SAD around the Median prediction.
1600            MinSAD=SAD
1601            If Motion Vector equal to Previous frame motion vector
1602                    and MinSAD<PrevFrmSAD goto Step 10.
1603            If SAD<=256 goto Step 10.
1604    */
1605    
1606    // Prepare for main loop
1607    
1608            *currMV=pmv[0];         /* current best := median prediction */
1609            if (!(MotionFlags & PMV_HALFPEL16))
1610            {
1611                    currMV->x = EVEN(currMV->x);
1612                    currMV->y = EVEN(currMV->y);
1613            }
1614    
1615            if (currMV->x > max_dx)
1616                    currMV->x=max_dx;
1617            if (currMV->x < min_dx)
1618                    currMV->x=min_dx;
1619            if (currMV->y > max_dy)
1620                    currMV->y=max_dy;
1621            if (currMV->y < min_dy)
1622                    currMV->y=min_dy;
1623    
1624    /***************** This is predictor SET A: only median prediction ******************/
1625    
1626            iMinSAD = sad16( cur,
1627                    get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),
1628                    iEdgedWidth, MV_MAX_ERROR);
1629            iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);
1630    
1631    // thresh1 is fixed to 256
1632            if ( (iMinSAD < 256 ) || ( (MVequal(*currMV, prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )
1633                    {
1634                            if (MotionFlags & PMV_QUICKSTOP16)
1635                                    goto EPZS16_Terminate_without_Refine;
1636                            if (MotionFlags & PMV_EARLYSTOP16)
1637                                    goto EPZS16_Terminate_with_Refine;
1638                    }
1639    
1640    /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
1641    
1642    // previous frame MV
1643            CHECK_MV16_CANDIDATE(prevMB->mvs[0].x,prevMB->mvs[0].y);
1644    
1645    // set threshhold based on Min of Prediction and SAD of collocated block
1646    // CHECK_MV16 always uses iSAD for the SAD of last vector to check, so now iSAD is what we want
1647    
1648            if ((x==0) && (y==0) )
1649            {
1650                    thresh2 =  512;
1651            }
1652            else
1653            {
1654    /* T_k = 1.2 * MIN(SAD_top,SAD_left,SAD_topleft,SAD_coll) +128;   [Tourapis, 2002] */
1655    
1656                    thresh2 = MIN(psad[0],iSAD)*6/5 + 128;
1657            }
1658    
1659    // MV=(0,0) is often a good choice
1660    
1661            CHECK_MV16_ZERO;
1662    
1663    
1664    // left neighbour, if allowed
1665            if (x != 0)
1666            {
1667                    if (!(MotionFlags & PMV_HALFPEL16 ))
1668                    {       pmv[1].x = EVEN(pmv[1].x);
1669                            pmv[1].y = EVEN(pmv[1].y);
1670                    }
1671                    CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1672            }
1673    
1674    // top neighbour, if allowed
1675            if (y != 0)
1676            {
1677                    if (!(MotionFlags & PMV_HALFPEL16 ))
1678                    {       pmv[2].x = EVEN(pmv[2].x);
1679                            pmv[2].y = EVEN(pmv[2].y);
1680                    }
1681                    CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1682    
1683    // top right neighbour, if allowed
1684                    if ((uint32_t)x != (iWcount-1))
1685                    {
1686                            if (!(MotionFlags & PMV_HALFPEL16 ))
1687                            {       pmv[3].x = EVEN(pmv[3].x);
1688                                    pmv[3].y = EVEN(pmv[3].y);
1689                            }
1690                            CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);
1691                    }
1692            }
1693    
1694    /* Terminate if MinSAD <= T_2
1695       Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
1696    */
1697    
1698            if ( (iMinSAD <= thresh2)
1699                    || ( MVequal(*currMV,prevMB->mvs[0]) && ((uint32_t)iMinSAD <= prevMB->sad16) ) )
1700                    {
1701                            if (MotionFlags & PMV_QUICKSTOP16)
1702                                    goto EPZS16_Terminate_without_Refine;
1703                            if (MotionFlags & PMV_EARLYSTOP16)
1704                                    goto EPZS16_Terminate_with_Refine;
1705                    }
1706    
1707    /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/
1708    
1709            backupMV = prevMB->mvs[0];              // collocated MV
1710            backupMV.x += (prevMB->mvs[0].x - oldMB->mvs[0].x );    // acceleration X
1711            backupMV.y += (prevMB->mvs[0].y - oldMB->mvs[0].y );    // acceleration Y
1712    
1713            CHECK_MV16_CANDIDATE(backupMV.x,backupMV.y);
1714    
1715    // left neighbour
1716            if (x != 0)
1717                    CHECK_MV16_CANDIDATE((prevMB-1)->mvs[0].x,(prevMB-1)->mvs[0].y);
1718    
1719    // top neighbour
1720            if (y != 0)
1721                    CHECK_MV16_CANDIDATE((prevMB-iWcount)->mvs[0].x,(prevMB-iWcount)->mvs[0].y);
1722    
1723    // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs
1724    
1725            if ((uint32_t)x != iWcount-1)
1726                    CHECK_MV16_CANDIDATE((prevMB+1)->mvs[0].x,(prevMB+1)->mvs[0].y);
1727    
1728    // bottom neighbour, dito
1729            if ((uint32_t)y != iHcount-1)
1730                    CHECK_MV16_CANDIDATE((prevMB+iWcount)->mvs[0].x,(prevMB+iWcount)->mvs[0].y);
1731    
1732    /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */
1733            if (iMinSAD <= thresh2)
1734                    {
1735                            if (MotionFlags & PMV_QUICKSTOP16)
1736                                    goto EPZS16_Terminate_without_Refine;
1737                            if (MotionFlags & PMV_EARLYSTOP16)
1738                                    goto EPZS16_Terminate_with_Refine;
1739                    }
1740    
1741    /************ (if Diamond Search)  **************/
1742    
1743            backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1744    
1745    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
1746    
1747            if (MotionFlags & PMV_USESQUARES16)
1748                    EPZSMainSearchPtr = Square16_MainSearch;
1749            else
1750                    EPZSMainSearchPtr = Diamond16_MainSearch;
1751    
1752            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1753                            x, y,
1754                            currMV->x, currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1755                            2, iFcode, iQuant, 0);
1756    
1757            if (iSAD < iMinSAD)
1758            {
1759                    *currMV = newMV;
1760                    iMinSAD = iSAD;
1761            }
1762    
1763    
1764            if (MotionFlags & PMV_EXTSEARCH16)
1765            {
1766    /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
1767    
1768                    if (!(MVequal(pmv[0],backupMV)) )
1769                    {
1770                            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1771                                    x, y,
1772                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1773                                    pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
1774                    }
1775    
1776                    if (iSAD < iMinSAD)
1777                    {
1778                            *currMV = newMV;
1779                            iMinSAD = iSAD;
1780                    }
1781    
1782                    if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1783                    {
1784                            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1785                                    x, y,
1786                            0, 0, iMinSAD, &newMV,
1787                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
1788    
1789                            if (iSAD < iMinSAD)
1790                            {
1791                                    *currMV = newMV;
1792                                    iMinSAD = iSAD;
1793                            }
1794                    }
1795            }
1796    
1797    /***************        Choose best MV found     **************/
1798    
1799    EPZS16_Terminate_with_Refine:
1800            if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
1801                    iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1802                                    x, y,
1803                                    currMV, iMinSAD,
1804                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1805    
1806    EPZS16_Terminate_without_Refine:
1807    
1808            *oldMB = *prevMB;
1809    
1810            currPMV->x = currMV->x - pmv[0].x;
1811            currPMV->y = currMV->y - pmv[0].y;
1812            return iMinSAD;
1813    }
1814    
1815    
1816    int32_t EPZSSearch8(
1817                                            const uint8_t * const pRef,
1818                                            const uint8_t * const pRefH,
1819                                            const uint8_t * const pRefV,
1820                                            const uint8_t * const pRefHV,
1821                                            const IMAGE * const pCur,
1822                                            const int x, const int y,
1823                                            const int start_x, const int start_y,
1824                                            const uint32_t MotionFlags,
1825                                            const uint32_t iQuant,
1826                                            const uint32_t iFcode,
1827                                            const MBParam * const pParam,
1828                                            const MACROBLOCK * const pMBs,
1829                                            const MACROBLOCK * const prevMBs,
1830                                            VECTOR * const currMV,
1831                                            VECTOR * const currPMV)
1832    {
1833    /* Please not that EPZS might not be a good choice for 8x8-block motion search ! */
1834    
1835            const uint32_t iWcount = pParam->mb_width;
1836            const int32_t iWidth = pParam->width;
1837            const int32_t iHeight = pParam->height;
1838            const int32_t iEdgedWidth = pParam->edged_width;
1839    
1840            const uint8_t * cur = pCur->y + x*8 + y*8*iEdgedWidth;
1841    
1842            int32_t iDiamondSize=1;
1843    
1844            int32_t min_dx;
1845            int32_t max_dx;
1846            int32_t min_dy;
1847            int32_t max_dy;
1848    
1849            VECTOR newMV;
1850            VECTOR backupMV;
1851    
1852            VECTOR pmv[4];
1853            int32_t psad[8];
1854    
1855            const   int32_t iSubBlock = ((y&1)<<1) + (x&1);
1856    
1857    //      const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1858            const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;
1859    
1860            int32_t bPredEq;
1861            int32_t iMinSAD,iSAD=9999;
1862    
1863            MainSearch8FuncPtr EPZSMainSearchPtr;
1864    
1865    /* Get maximum range */
1866            get_range(&min_dx, &max_dx, &min_dy, &max_dy,
1867                            x, y, 8, iWidth, iHeight, iFcode);
1868    
1869    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
1870    
1871            if (!(MotionFlags & PMV_HALFPEL8 ))
1872            { min_dx = EVEN(min_dx);
1873              max_dx = EVEN(max_dx);
1874              min_dy = EVEN(min_dy);
1875              max_dy = EVEN(max_dy);
1876            }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1877    
1878            bPredEq  = get_pmvdata(pMBs, x>>1, y>>1, iWcount, iSubBlock, pmv, psad);
1879    
1880    
1881    /* Step 4: Calculate SAD around the Median prediction.
1882            MinSAD=SAD
1883            If Motion Vector equal to Previous frame motion vector
1884                    and MinSAD<PrevFrmSAD goto Step 10.
1885            If SAD<=256 goto Step 10.
1886    */
1887    
1888    // Prepare for main loop
1889    
1890    
1891            if (!(MotionFlags & PMV_HALFPEL8))
1892            {
1893                    currMV->x = EVEN(currMV->x);
1894                    currMV->y = EVEN(currMV->y);
1895            }
1896    
1897            if (currMV->x > max_dx)
1898                    currMV->x=max_dx;
1899            if (currMV->x < min_dx)
1900                    currMV->x=min_dx;
1901            if (currMV->y > max_dy)
1902                    currMV->y=max_dy;
1903            if (currMV->y < min_dy)
1904                    currMV->y=min_dy;
1905    
1906    /***************** This is predictor SET A: only median prediction ******************/
1907    
1908    
1909            iMinSAD = sad8( cur,
1910                    get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),
1911                    iEdgedWidth);
1912            iMinSAD += calc_delta_8(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);
1913    
1914    
1915    // thresh1 is fixed to 256
1916            if (iMinSAD < 256/4 )
1917                    {
1918                            if (MotionFlags & PMV_QUICKSTOP8)
1919                                    goto EPZS8_Terminate_without_Refine;
1920                            if (MotionFlags & PMV_EARLYSTOP8)
1921                                    goto EPZS8_Terminate_with_Refine;
1922                    }
1923    
1924    /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
1925    
1926    
1927    // MV=(0,0) is often a good choice
1928            CHECK_MV8_ZERO;
1929    
1930    // previous frame MV
1931            CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);
1932    
1933    // left neighbour, if allowed
1934            if (psad[1] != MV_MAX_ERROR)
1935            {
1936                    if (!(MotionFlags & PMV_HALFPEL8 ))
1937                    {       pmv[1].x = EVEN(pmv[1].x);
1938                            pmv[1].y = EVEN(pmv[1].y);
1939                    }
1940                    CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
1941            }
1942    
1943    // top neighbour, if allowed
1944            if (psad[2] != MV_MAX_ERROR)
1945            {
1946                    if (!(MotionFlags & PMV_HALFPEL8 ))
1947                    {       pmv[2].x = EVEN(pmv[2].x);
1948                            pmv[2].y = EVEN(pmv[2].y);
1949                    }
1950                    CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
1951    
1952    // top right neighbour, if allowed
1953                    if (psad[3] != MV_MAX_ERROR)
1954                    {
1955                            if (!(MotionFlags & PMV_HALFPEL8 ))
1956                            {       pmv[3].x = EVEN(pmv[3].x);
1957                                    pmv[3].y = EVEN(pmv[3].y);
1958                            }
1959                            CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);
1960                    }
1961            }
1962    
1963    /*  // this bias is zero anyway, at the moment!
1964    
1965            if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) ) // && (iMinSAD <= iQuant * 96)
1966                    iMinSAD -= MV8_00_BIAS;
1967    
1968    */
1969    
1970    /* Terminate if MinSAD <= T_2
1971       Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
1972    */
1973    
1974            if (iMinSAD < 512/4)    /* T_2 == 512/4 hardcoded */
1975                    {
1976                            if (MotionFlags & PMV_QUICKSTOP8)
1977                                    goto EPZS8_Terminate_without_Refine;
1978                            if (MotionFlags & PMV_EARLYSTOP8)
1979                                    goto EPZS8_Terminate_with_Refine;
1980                    }
1981    
1982    /************ (Diamond Search)  **************/
1983    
1984            backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1985    
1986            if (!(MotionFlags & PMV_HALFPELDIAMOND8))
1987                    iDiamondSize *= 2;
1988    
1989    /* default: use best prediction as starting point for one call of EPZS_MainSearch */
1990    
1991    /* // there is no EPZS^2 for inter4v at the moment
1992    
1993            if (MotionFlags & PMV_USESQUARES8)
1994                    EPZSMainSearchPtr = Square8_MainSearch;
1995            else
1996    */
1997    
1998            EPZSMainSearchPtr = Diamond8_MainSearch;
1999    
2000            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
2001                    x, y,
2002                    currMV->x, currMV->y, iMinSAD, &newMV,
2003                    pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2004                    iDiamondSize, iFcode, iQuant, 0);
2005    
2006    
2007            if (iSAD < iMinSAD)
2008            {
2009                    *currMV = newMV;
2010                    iMinSAD = iSAD;
2011            }
2012    
2013            if (MotionFlags & PMV_EXTSEARCH8)
2014            {
2015    /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
2016    
2017                    if (!(MVequal(pmv[0],backupMV)) )
2018                    {
2019                            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
2020                                    x, y,
2021                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,
2022                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);
2023    
2024                            if (iSAD < iMinSAD)
2025                            {
2026                                    *currMV = newMV;
2027                                    iMinSAD = iSAD;
2028                            }
2029                    }
2030    
2031                    if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
2032                    {
2033                            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
2034                                    x, y,
2035                            0, 0, iMinSAD, &newMV,
2036                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);
2037    
2038                            if (iSAD < iMinSAD)
2039                            {
2040                                    *currMV = newMV;
2041                                    iMinSAD = iSAD;
2042                            }
2043                    }
2044            }
2045    
2046    /***************        Choose best MV found     **************/
2047    
2048    EPZS8_Terminate_with_Refine:
2049            if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
2050                    iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,
2051                                    x, y,
2052                                    currMV, iMinSAD,
2053                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
2054    
2055    EPZS8_Terminate_without_Refine:
2056    
2057            currPMV->x = currMV->x - pmv[0].x;
2058            currPMV->y = currMV->y - pmv[0].y;
2059            return iMinSAD;
2060    }
2061    
2062    
2063    
2064    
2065    
2066    /* ***********************************************************
2067            bvop motion estimation
2068    // TODO: need to incorporate prediction here (eg. sad += calc_delta_16)
2069    ***************************************************************/
2070    
2071    
2072    void MotionEstimationBVOP(
2073                            MBParam * const pParam,
2074                            FRAMEINFO * const frame,
2075    
2076                            // forward (past) reference
2077                            const MACROBLOCK * const f_mbs,
2078                        const IMAGE * const f_ref,
2079                            const IMAGE * const f_refH,
2080                        const IMAGE * const f_refV,
2081                            const IMAGE * const f_refHV,
2082                            // backward (future) reference
2083                            const MACROBLOCK * const b_mbs,
2084                        const IMAGE * const b_ref,
2085                            const IMAGE * const b_refH,
2086                        const IMAGE * const b_refV,
2087                            const IMAGE * const b_refHV)
2088    {
2089        const uint32_t mb_width = pParam->mb_width;
2090        const uint32_t mb_height = pParam->mb_height;
2091            const int32_t edged_width = pParam->edged_width;
2092    
2093            uint32_t i,j;
2094    
2095            int32_t f_sad16;
2096            int32_t b_sad16;
2097            int32_t i_sad16;
2098            int32_t d_sad16;
2099            int32_t best_sad;
2100    
2101            VECTOR pmv_dontcare;
2102    
2103            // note: i==horizontal, j==vertical
2104        for (j = 0; j < mb_height; j++)
2105            {
2106                    for (i = 0; i < mb_width; i++)
2107                    {
2108                            MACROBLOCK *mb = &frame->mbs[i + j*mb_width];
2109                            const MACROBLOCK *f_mb = &f_mbs[i + j*mb_width];
2110                            const MACROBLOCK *b_mb = &b_mbs[i + j*mb_width];
2111    
2112                            if (b_mb->mode == MODE_INTER
2113                                    && b_mb->cbp == 0
2114                                    && b_mb->mvs[0].x == 0
2115                                    && b_mb->mvs[0].y == 0)
2116                            {
2117                                    mb->mode = MODE_NOT_CODED;
2118                                    mb->mvs[0].x = 0;
2119                                    mb->mvs[0].y = 0;
2120                                    mb->b_mvs[0].x = 0;
2121                                    mb->b_mvs[0].y = 0;
2122                                    continue;
2123                            }
2124    
2125    
2126                            // forward search
2127                            f_sad16 = SEARCH16(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2128                                                    &frame->image,
2129                                                    i, j,
2130                                                    frame->motion_flags,  frame->quant, frame->fcode,
2131                                                    pParam,
2132                                                    f_mbs, f_mbs /* todo */,
2133                                                    &mb->mvs[0], &pmv_dontcare);    // ignore pmv
2134    
2135                            // backward search
2136                            b_sad16 = SEARCH16(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
2137                                                    &frame->image,
2138                                                    i, j,
2139                                                    frame->motion_flags,  frame->quant, frame->bcode,
2140                                                    pParam,
2141                                                    b_mbs, b_mbs, /* todo */
2142                                                    &mb->b_mvs[0], &pmv_dontcare);  // ignore pmv
2143    
2144                            // interpolate search (simple, but effective)
2145                            i_sad16 = sad16bi_c(
2146                                            frame->image.y + i*16 + j*16*edged_width,
2147                                            get_ref(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2148                                                    i, j, 16, mb->mvs[0].x, mb->mvs[0].y, edged_width),
2149                                            get_ref(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
2150                                                    i, j, 16, mb->b_mvs[0].x, mb->b_mvs[0].x, edged_width),
2151                                            edged_width);
2152    
2153                            // TODO: direct search
2154                            // predictor + range of [-32,32]
2155                            d_sad16 = 65535;
2156    
2157    
2158                            if (f_sad16 < b_sad16)
2159                            {
2160                                    best_sad = f_sad16;
2161                                    mb->mode = MODE_FORWARD;
2162                            }
2163                            else
2164                            {
2165                                    best_sad = b_sad16;
2166                                    mb->mode = MODE_BACKWARD;
2167                            }
2168    
2169                            if (i_sad16 < best_sad)
2170                            {
2171                                    best_sad = i_sad16;
2172                                    mb->mode = MODE_INTERPOLATE;
2173                            }
2174    
2175                            if (d_sad16 < best_sad)
2176                            {
2177                                    best_sad = d_sad16;
2178                                    mb->mode = MODE_DIRECT;
2179                            }
2180    
2181                    }
2182            }
2183    }

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

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