[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 3, Fri Mar 8 02:46:11 2002 UTC revision 175, Sun May 12 17:21: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 0
58    // how much a block's MV must differ from his neighbour
59    // to be search for INTER4V. The more, the faster...
60    
61  /* sad16(0,0) bias; mpeg4 spec suggests nb/2+1 */  /* sad16(0,0) bias; mpeg4 spec suggests nb/2+1 */
62  /* nb  = vop pixels * 2^(bpp-8) */  /* nb  = vop pixels * 2^(bpp-8) */
63  #define MV16_00_BIAS    (128+1)  #define MV16_00_BIAS    (128+1)
64    #define MV8_00_BIAS     (0)
65    
66  /* INTER bias for INTER/INTRA decision; mpeg4 spec suggests 2*nb */  /* INTER bias for INTER/INTRA decision; mpeg4 spec suggests 2*nb */
67  #define INTER_BIAS      512  #define MV16_INTER_BIAS 512
68    
69  /* Parameters which control inter/inter4v decision */  /* Parameters which control inter/inter4v decision */
70  #define IMV16X16                        5  #define IMV16X16                        5
# Line 60  Line 73 
73  #define NEIGH_TEND_16X16        2  #define NEIGH_TEND_16X16        2
74  #define NEIGH_TEND_8X8          2  #define NEIGH_TEND_8X8          2
75    
   
76  // fast ((A)/2)*2  // fast ((A)/2)*2
77  #define EVEN(A)         (((A)<0?(A)+1:(A)) & ~1)  #define EVEN(A)         (((A)<0?(A)+1:(A)) & ~1)
78    
79    #define MVzero(A) ( ((A).x)==(0) && ((A).y)==(0) )
80    #define MVequal(A,B) ( ((A).x)==((B).x) && ((A).y)==((B).y) )
81    
82    int32_t PMVfastSearch16(
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 159  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          const int search_range = 32 << (fcode - 1);      return NEIGH_TEND_8X8 * lambda_vec8[iQuant] * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));
     const int high = search_range - 1;  
     const int low = -search_range;  
   
         // convert full-pixel measurements to half pixel  
         const int hp_width = 2 * width;  
         const int hp_height = 2 * height;  
         const int hp_edge = 2 * block_sz;  
         const int hp_x = 2 * (x) * block_sz;            // we need _right end_ of block, not x-coordinate  
         const int hp_y = 2 * (y) * block_sz;            // same for _bottom end_  
   
     *max_dx = MIN(high, hp_width - hp_x);  
     *max_dy = MIN(high, hp_height - hp_y);  
     *min_dx = MAX(low,  -(hp_edge + hp_x));  
     *min_dy = MAX(low,  -(hp_edge + hp_y));  
250  }  }
251    
252    
 /* 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;  
         }  
 }  
   
253    
 /* This is somehow a copy of get_ref, but with MV instead of X,Y */  
254    
 static __inline const uint8_t * get_ref_mv(  
                                 const uint8_t * const refn,  
                                 const uint8_t * const refh,  
                                 const uint8_t * const refv,  
                                 const uint8_t * const refhv,  
                                 const uint32_t x, const uint32_t y,  
                                 const uint32_t block,                   // block dimension, 8 or 16  
                                 const VECTOR* mv,       // measured in half-pel!  
                                 const uint32_t stride)  
 {  
         switch ( (((mv->x)&1)<<1) + ((mv->y)&1) )  
     {  
         case 0 : return refn + (x*block+(mv->x)/2) + (y*block+(mv->y)/2)*stride;  
         case 1 : return refv + (x*block+(mv->x)/2) + (y*block+((mv->y)-1)/2)*stride;  
         case 2 : return refh + (x*block+((mv->x)-1)/2) + (y*block+(mv->y)/2)*stride;  
         default :  
         case 3 : return refhv + (x*block+((mv->x)-1)/2) + (y*block+((mv->y)-1)/2)*stride;  
         }  
 }  
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    
                 /* decide: MODE_INTER or MODE_INTRA  
                         if (dev_intra < sad_inter - 2 * nb) use_intra  
                 */  
303    
304                  deviation = dev16(pCurrent->y + j*16 + i*16*pParam->edged_width, pParam->edged_width);                          if (0 < (pMB->sad16 - MV16_INTER_BIAS))
305                            {
306                                    int32_t deviation;
307                                    deviation = dev16(pCurrent->y + x*16 + y*16*pParam->edged_width,
308                                                             pParam->edged_width);
309    
310                  if (deviation < (sad16 - INTER_BIAS))                                  if (deviation < (pMB->sad16 - MV16_INTER_BIAS))
311                  {                  {
312                          pMB->mode = MODE_INTRA;                          pMB->mode = MODE_INTRA;
313                          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]
314                          pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = 0;                                                                   = pMB->mvs[2] = pMB->mvs[3] = zeroMV;
315                                            pMB->sad16 = pMB->sad8[0] = pMB->sad8[1]
316                                                                 = pMB->sad8[2] = pMB->sad8[3] = 0;
317    
318                          iIntra++;                          iIntra++;
319                          if(iIntra >= iLimit)                          if(iIntra >= iLimit)
# Line 312  Line 321 
321    
322                          continue;                          continue;
323                  }                  }
324                            }
325                            pMB->mode = MODE_INTER;
326                            pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mv16;
327               pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = pMB->sad16;
328                    }
329    
330            // we try to do as few INTER4V-searches as possible. So we split ME in two parts, normal
331            // SEARCH16 and only for special blocks SEARCH8. May this should be modified for quality
332            // levels.
333    
                 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]);  
334    
                         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]);  
335    
336                          pMB->sad8[2] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,          if (current->global_flags & XVID_INTER4V)
337                                          2 * j, 2 * i + 1, mv16.x, mv16.y, pParam->motion_flags,                  for (y = 0; y < iHcount; y++)
338                                          pParam, pMBs, &pMB->mvs[2], &pMB->pmvs[2]);                          for (x = 0; x < iWcount; x++)
339                            {
340                                    MACROBLOCK* const pMB = &pMBs[x + y * iWcount];
341    
342                                    if (pMB->mode == MODE_INTRA)
343                                            continue;
344    
                         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]);  
345    
346                          sad8 = pMB->sad8[0] + pMB->sad8[1] + pMB->sad8[2] + pMB->sad8[3];                                  if ( (!(current->global_flags & XVID_LUMIMASKING) || pMB->dquant == NO_CHANGE) )
347                  }                                  {
348                                    int32_t neigh=0;
349    
350                                    if (x>0)
351                                    {       neigh += abs((pMB->mv16.x)-((pMB-1)->mv16.x));
352                                            neigh += abs((pMB->mv16.y)-((pMB-1)->mv16.y));
353                                    }
354                                    if (y>0)
355                                    {       neigh += abs((pMB->mv16.x)-((pMB-iWcount)->mv16.x));
356                                            neigh += abs((pMB->mv16.y)-((pMB-iWcount)->mv16.y));
357                                    }
358                                    if (x<(iWcount-1))
359                                    {       neigh += abs((pMB->mv16.x)-((pMB+1)->mv16.x));
360                                            neigh += abs((pMB->mv16.y)-((pMB+1)->mv16.y));
361                                    }
362                                    if (y<(iHcount-1))
363                                    {       neigh += abs((pMB->mv16.x)-((pMB+iHcount)->mv16.x));
364                                            neigh += abs((pMB->mv16.y)-((pMB+iHcount)->mv16.y));
365                                    }
366    
367                                    if (neigh > NEIGH_MOVE_THRESH)
368                                    {
369                                            int32_t sad8 = IMV16X16 * current->quant;
370    
371                                            if (sad8 < pMB->sad16)
372                                            sad8 += pMB->sad8[0]
373                                                    = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
374                                                                   2*x, 2*y, pMB->mv16.x, pMB->mv16.y,
375                                                                       current->motion_flags, current->quant, current->fcode,
376                                                                   pParam, pMBs, prevMBs, &pMB->mvs[0], &pMB->pmvs[0]);
377    
378                                            if (sad8 < pMB->sad16)
379                                            sad8 += pMB->sad8[1]
380                                                    = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
381                                           2*x+1, 2*y, pMB->mv16.x, pMB->mv16.y,
382                                                            current->motion_flags, current->quant, current->fcode,
383                                                            pParam, pMBs, prevMBs, &pMB->mvs[1], &pMB->pmvs[1]);
384    
385                                            if (sad8 < pMB->sad16)
386                                            sad8 += pMB->sad8[2]
387                                                    = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
388                                                            2*x, 2*y+1, pMB->mv16.x, pMB->mv16.y,
389                                                            current->motion_flags, current->quant, current->fcode,
390                                                            pParam, pMBs, prevMBs, &pMB->mvs[2], &pMB->pmvs[2]);
391    
392                                            if (sad8 < pMB->sad16)
393                                            sad8 += pMB->sad8[3]
394                                                    = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
395                                                            2*x+1, 2*y+1, pMB->mv16.x, pMB->mv16.y,
396                                                            current->motion_flags, current->quant, current->fcode,
397                                                            pParam, pMBs, prevMBs, &pMB->mvs[3], &pMB->pmvs[3]);
398    
399                  /* decide: MODE_INTER or MODE_INTER4V                  /* decide: MODE_INTER or MODE_INTER4V
400                          mpeg4:   if (sad8 < sad16 - nb/2+1) use_inter4v                             mpeg4:   if (sad8 < pMB->sad16 - nb/2+1) use_inter4v
401                  */                  */
402    
403                  if (pMB->dquant == NO_CHANGE) {                                          if (sad8 < pMB->sad16)
                         if (((pParam->global_flags & XVID_INTER4V)==0) ||  
                                 (sad16 < (sad8 + (int32_t)(IMV16X16 * pParam->quant)))) {  
   
                                 sad8 = sad16;  
                                 pMB->mode = MODE_INTER;  
                                 pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = mv16.x;  
                                 pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = mv16.y;  
                                 pMB->pmvs[0].x = pmv16.x;  
                                 pMB->pmvs[0].y = pmv16.y;  
                         }  
                         else  
                                 pMB->mode = MODE_INTER4V;  
                 }  
                 else  
404                  {                  {
405                          sad8 = sad16;                                                  pMB->mode = MODE_INTER4V;
406                          pMB->mode = MODE_INTER;                        pMB->sad8[0] *= 4;
407                          pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = mv16.x;                                                  pMB->sad8[1] *= 4;
408                          pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = mv16.y;                                                  pMB->sad8[2] *= 4;
409                          pMB->pmvs[0].x = pmv16.x;                                                  pMB->sad8[3] *= 4;
410                          pMB->pmvs[0].y = pmv16.y;                                                  continue;
411                  }                  }
412    
413                                            pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mv16;
414          }          }
415    
         return 0;  
416  }  }
417    
418  #define MVzero(A) ( ((A).x)==(0) && ((A).y)==(0) )                  // get_pmv has to be called again, because inter4v changes predictors
419    
420  #define MVequal(A,B) ( ((A).x)==((B).x) && ((A).y)==((B).y) )                          pmv = get_pmv(pMBs, x, y, pParam->mb_width, 0);
421                            pMB->pmvs[0].x = pMB->mv16.x - pmv.x;   /* the other pmvs are only needed in INTER4V-mode */
422                            pMB->pmvs[0].y = pMB->mv16.y - pmv.y;
423    
424                            }
425    
426            return 0;
427    }
428    
429  #define CHECK_MV16_ZERO {\  #define CHECK_MV16_ZERO {\
430    if ( (0 <= max_dx) && (0 >= min_dx) \    if ( (0 <= max_dx) && (0 >= min_dx) \
431      && (0 <= max_dy) && (0 >= min_dy) ) \      && (0 <= max_dy) && (0 >= min_dy) ) \
432    { \    { \
433      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); \
434      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; \  
435      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
436      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \
437  }  }
438    
439    #define NOCHECK_MV16_CANDIDATE(X,Y) { \
440        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
441        iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\
442        if (iSAD < iMinSAD) \
443        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
444    }
445    
446  #define CHECK_MV16_CANDIDATE(X,Y) { \  #define CHECK_MV16_CANDIDATE(X,Y) { \
447    if ( ((X) <= max_dx) && ((X) >= min_dx) \    if ( ((X) <= max_dx) && ((X) >= min_dx) \
448      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
449    { \    { \
450      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); \
451      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);\
452      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
453      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
454  }  }
# Line 400  Line 458 
458      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
459    { \    { \
460      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); \
461      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);\
462      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
463      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
464  }  }
# Line 410  Line 468 
468      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
469    { \    { \
470      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); \
471      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);\
472      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
473      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
474  }  }
# Line 418  Line 476 
476    
477  #define CHECK_MV8_ZERO {\  #define CHECK_MV8_ZERO {\
478    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); \
479    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);\
480    if (iSAD < iMinSAD) \    if (iSAD < iMinSAD) \
481    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \
482  }  }
483    
484    #define NOCHECK_MV8_CANDIDATE(X,Y) \
485      { \
486        iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
487        iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\
488        if (iSAD < iMinSAD) \
489        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
490    }
491    
492  #define CHECK_MV8_CANDIDATE(X,Y) { \  #define CHECK_MV8_CANDIDATE(X,Y) { \
493    if ( ((X) <= max_dx) && ((X) >= min_dx) \    if ( ((X) <= max_dx) && ((X) >= min_dx) \
494      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
495    { \    { \
496      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); \
497      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);\
498      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
499      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
500  }  }
# Line 439  Line 504 
504      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
505    { \    { \
506      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); \
507      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);\
508      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
509      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
510  }  }
# Line 449  Line 514 
514      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
515    { \    { \
516      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); \
517      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);\
518      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
519      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
520  }  }
# Line 464  Line 529 
529                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
530                                          const int x, const int y,                                          const int x, const int y,
531                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
532                                            const uint32_t iQuant,
533                                            const uint32_t iFcode,
534                                          MBParam * const pParam,                                          MBParam * const pParam,
535                                          MACROBLOCK * const pMBs,                                          const MACROBLOCK * const pMBs,
536                                            const MACROBLOCK * const prevMBs,
537                                          VECTOR * const currMV,                                          VECTOR * const currMV,
538                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
539  {  {
540          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
         const int32_t iQuant = pParam->quant;  
541          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
542          int32_t iSAD;          int32_t iSAD;
543          int32_t pred_x,pred_y;          int32_t pred_x,pred_y;
# Line 493  Line 560 
560  }  }
561  */  */
562    
563  int32_t PMVfastSearch16_MainSearch(  int32_t Diamond16_MainSearch(
564                                          const uint8_t * const pRef,                                          const uint8_t * const pRef,
565                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
566                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
# Line 550  Line 617 
617          return iMinSAD;          return iMinSAD;
618  }  }
619    
620  int32_t PMVfastSearch16_Refine(  int32_t Square16_MainSearch(
621                                          const uint8_t * const pRef,                                          const uint8_t * const pRef,
622                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
623                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
624                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
625                                          const uint8_t * const cur,                                          const uint8_t * const cur,
626                                          const int x, const int y,                                          const int x, const int y,
627                                          VECTOR * const currMV,                                          int32_t startx, int32_t starty,
628                                          int32_t iMinSAD,                                          int32_t iMinSAD,
629                                            VECTOR * const currMV,
630                                          const VECTOR * const pmv,                                          const VECTOR * const pmv,
631                                          const int32_t min_dx, const int32_t max_dx,                                          const int32_t min_dx, const int32_t max_dx,
632                                          const int32_t min_dy, const int32_t max_dy,                                          const int32_t min_dy, const int32_t max_dy,
633                                            const int32_t iEdgedWidth,
634                                            const int32_t iDiamondSize,
635                                          const int32_t iFcode,                                          const int32_t iFcode,
636                                          const int32_t iQuant,                                          const int32_t iQuant,
637                                          const int32_t iEdgedWidth)                                          int iFound)
638  {  {
639  /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */  /* Do a square search around given starting point, return SAD of best */
640    
641            int32_t iDirection=0;
642          int32_t iSAD;          int32_t iSAD;
643          VECTOR backupMV = *currMV;          VECTOR backupMV;
644            backupMV.x = startx;
645          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)  
646    
647  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;  
648    
649          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;  /*   new direction are extra, so 1-4 is normal diamond
650          537
651          1*2
652          648
653    */
654    
655          int32_t iDiamondSize;          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
656            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
657            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
658            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
659    
660          int32_t min_dx;          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
661          int32_t max_dx;          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
662          int32_t min_dy;          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
663          int32_t max_dy;          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
664    
         int32_t iFound;  
665    
666          VECTOR newMV;          if (iDirection)
667          VECTOR backupMV;        /* just for PMVFAST */                  while (!iFound)
668                    {
669                            iFound = 1;
670                            backupMV=*currMV;
671    
672          VECTOR pmv[4];                          switch (iDirection)
673          int32_t psad[4];                          {
674                                    case 1:
675                                            CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);
676                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
677                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
678                                            break;
679                                    case 2:
680                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
681                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
682                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
683                                            break;
684    
685          MACROBLOCK * const pMB = pMBs + x + y * iWcount;                                  case 3:
686                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
687                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
688                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
689                                            break;
690    
691          static int32_t threshA,threshB;                                  case 4:
692          int32_t bPredEq;                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
693          int32_t iMinSAD,iSAD;                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
694                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
695                                            break;
696    
697  /* Get maximum range */                                  case 5:
698          get_range(&min_dx, &max_dx, &min_dy, &max_dy,                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
699                          x, y, 16, iWidth, iHeight, iFcode);                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
700                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
701                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
702                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
703                                            break;
704    
705  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */                                  case 6:
706                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
707                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
708    
709          if (!(MotionFlags & PMV_HALFPEL16 ))                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
710          { min_dx = EVEN(min_dx);                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
711            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; */  
712    
713                                            break;
714    
715          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);                                  case 7:
716                                            CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);
717                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
718                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
719                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
720                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
721                                            break;
722    
723          if ((x==0) && (y==0) )                                  case 8:
724          {                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
725                  threshA =  512;                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
726                  threshB = 1024;                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
727                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
728                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
729                                            break;
730                            default:
731                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
732                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
733                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
734                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
735    
736                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
737                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
738                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
739                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
740                                            break;
741                            }
742          }          }
743          else          else
744          {          {
745                  threshA = psad[0];                          currMV->x = startx;
746                  threshB = threshA+256;                          currMV->y = starty;
747                  if (threshA< 512) threshA =  512;                  }
748                  if (threshA>1024) threshA = 1024;          return iMinSAD;
                 if (threshB>1792) threshB = 1792;  
749          }          }
750    
         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.  
 */  
751    
752          if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536) || (bPredEq) )  int32_t Full16_MainSearch(
753                  iDiamondSize=1; // halfpel!                                          const uint8_t * const pRef,
754          else                                          const uint8_t * const pRefH,
755                  iDiamondSize=2; // halfpel!                                          const uint8_t * const pRefV,
756                                            const uint8_t * const pRefHV,
757                                            const uint8_t * const cur,
758                                            const int x, const int y,
759                                            int32_t startx, int32_t starty,
760                                            int32_t iMinSAD,
761                                            VECTOR * const currMV,
762                                            const VECTOR * const pmv,
763                                            const int32_t min_dx, const int32_t max_dx,
764                                            const int32_t min_dy, const int32_t max_dy,
765                                            const int32_t iEdgedWidth,
766                                            const int32_t iDiamondSize,
767                                            const int32_t iFcode,
768                                            const int32_t iQuant,
769                                            int iFound)
770    {
771            int32_t iSAD;
772            int32_t dx,dy;
773            VECTOR backupMV;
774            backupMV.x = startx;
775            backupMV.y = starty;
776    
777          if (!(MotionFlags & PMV_HALFPELDIAMOND16) )          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
778                  iDiamondSize*=2;                  for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
779                            NOCHECK_MV16_CANDIDATE(dx,dy);
780    
781            return iMinSAD;
782    }
783    
784    int32_t Full8_MainSearch(
785                                            const uint8_t * const pRef,
786                                            const uint8_t * const pRefH,
787                                            const uint8_t * const pRefV,
788                                            const uint8_t * const pRefHV,
789                                            const uint8_t * const cur,
790                                            const int x, const int y,
791                                            int32_t startx, int32_t starty,
792                                            int32_t iMinSAD,
793                                            VECTOR * const currMV,
794                                            const VECTOR * const pmv,
795                                            const int32_t min_dx, const int32_t max_dx,
796                                            const int32_t min_dy, const int32_t max_dy,
797                                            const int32_t iEdgedWidth,
798                                            const int32_t iDiamondSize,
799                                            const int32_t iFcode,
800                                            const int32_t iQuant,
801                                            int iFound)
802    {
803            int32_t iSAD;
804            int32_t dx,dy;
805            VECTOR backupMV;
806            backupMV.x = startx;
807            backupMV.y = starty;
808    
809            for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
810                    for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
811                            NOCHECK_MV8_CANDIDATE(dx,dy);
812    
813            return iMinSAD;
814    }
815    
816    
817    
818    int32_t Halfpel16_Refine(
819            const uint8_t * const pRef,
820            const uint8_t * const pRefH,
821            const uint8_t * const pRefV,
822            const uint8_t * const pRefHV,
823            const uint8_t * const cur,
824            const int x, const int y,
825            VECTOR * const currMV,
826            int32_t iMinSAD,
827            const VECTOR * const pmv,
828            const int32_t min_dx, const int32_t max_dx,
829            const int32_t min_dy, const int32_t max_dy,
830            const int32_t iFcode,
831            const int32_t iQuant,
832            const int32_t iEdgedWidth)
833    {
834    /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */
835    
836            int32_t iSAD;
837            VECTOR backupMV = *currMV;
838    
839            CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y-1);
840            CHECK_MV16_CANDIDATE(backupMV.x  ,backupMV.y-1);
841            CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y-1);
842            CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y);
843            CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y);
844            CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y+1);
845            CHECK_MV16_CANDIDATE(backupMV.x  ,backupMV.y+1);
846            CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y+1);
847    
848            return iMinSAD;
849    }
850    
851    #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
852    
853    
854    int32_t PMVfastSearch16(
855                                            const uint8_t * const pRef,
856                                            const uint8_t * const pRefH,
857                                            const uint8_t * const pRefV,
858                                            const uint8_t * const pRefHV,
859                                            const IMAGE * const pCur,
860                                            const int x, const int y,
861                                            const uint32_t MotionFlags,
862                                            const uint32_t iQuant,
863                                            const uint32_t iFcode,
864                                            const MBParam * const pParam,
865                                            const MACROBLOCK * const pMBs,
866                                            const MACROBLOCK * const prevMBs,
867                                            VECTOR * const currMV,
868                                            VECTOR * const currPMV)
869    {
870        const uint32_t iWcount = pParam->mb_width;
871            const int32_t iWidth = pParam->width;
872            const int32_t iHeight = pParam->height;
873            const int32_t iEdgedWidth = pParam->edged_width;
874    
875            const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
876    
877            int32_t iDiamondSize;
878    
879            int32_t min_dx;
880            int32_t max_dx;
881            int32_t min_dy;
882            int32_t max_dy;
883    
884            int32_t iFound;
885    
886            VECTOR newMV;
887            VECTOR backupMV;        /* just for PMVFAST */
888    
889            VECTOR pmv[4];
890            int32_t psad[4];
891    
892    //      const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
893            const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
894    
895            static int32_t threshA,threshB;
896            int32_t bPredEq;
897            int32_t iMinSAD,iSAD;
898    
899    /* Get maximum range */
900            get_range(&min_dx, &max_dx, &min_dy, &max_dy,
901                      x, y, 16, iWidth, iHeight, iFcode);
902    
903    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
904    
905            if (!(MotionFlags & PMV_HALFPEL16 ))
906            { min_dx = EVEN(min_dx);
907            max_dx = EVEN(max_dx);
908            min_dy = EVEN(min_dy);
909            max_dy = EVEN(max_dy);
910            }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
911    
912    
913            bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
914    
915            if ((x==0) && (y==0) )
916            {
917                    threshA =  512;
918                    threshB = 1024;
919    
920            }
921            else
922            {
923                    threshA = psad[0];
924                    threshB = threshA+256;
925                    if (threshA< 512) threshA =  512;
926                    if (threshA>1024) threshA = 1024;
927                    if (threshB>1792) threshB = 1792;
928            }
929    
930            iFound=0;
931    
932  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
933          MinSAD=SAD          MinSAD=SAD
# Line 688  Line 936 
936          If SAD<=256 goto Step 10.          If SAD<=256 goto Step 10.
937  */  */
938    
   
 // Prepare for main loop  
   
939          *currMV=pmv[0];         /* current best := prediction */          *currMV=pmv[0];         /* current best := prediction */
940          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16 ))
941          {       /* This should NOT be necessary! */          {       /* This should NOT be necessary! */
# Line 718  Line 963 
963          iMinSAD = sad16( cur,          iMinSAD = sad16( cur,
964                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),
965                  iEdgedWidth, MV_MAX_ERROR);                  iEdgedWidth, MV_MAX_ERROR);
966          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);
967    
968          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && (iMinSAD < pMB->sad16) ) )          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )
969            {
970                    if (iMinSAD < 2*iQuant) // high chances for SKIP-mode
971                    {
972                            if (!MVzero(*currMV))
973                  {                  {
974                                    iMinSAD += MV16_00_BIAS;
975                                    CHECK_MV16_ZERO;                // (0,0) saves space for letterboxed pictures
976                                    iMinSAD -= MV16_00_BIAS;
977                            }
978                    }
979    
980                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
981                                  goto step10b;                          goto PMVfast16_Terminate_without_Refine;
982                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
983                                  goto step10;                          goto PMVfast16_Terminate_with_Refine;
984                  }                  }
985    
986    
987    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
988       vector of the median.
989       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
990    */
991    
992            if ((bPredEq) && (MVequal(pmv[0],prevMB->mvs[0]) ) )
993                    iFound=2;
994    
995    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
996       Otherwise select large Diamond Search.
997    */
998    
999            if ( (!MVzero(pmv[0])) || (threshB<1536) || (bPredEq) )
1000                    iDiamondSize=1; // halfpel!
1001            else
1002                    iDiamondSize=2; // halfpel!
1003    
1004            if (!(MotionFlags & PMV_HALFPELDIAMOND16) )
1005                    iDiamondSize*=2;
1006    
1007  /*  /*
1008  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.
1009          Also calculate (0,0) but do not subtract offset.          Also calculate (0,0) but do not subtract offset.
1010          Let MinSAD be the smallest SAD up to this point.          Let MinSAD be the smallest SAD up to this point.
1011          If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
1012  */  */
1013    
1014  // (0,0) is always possible  // (0,0) is always possible
1015    
1016            if (!MVzero(pmv[0]))
1017          CHECK_MV16_ZERO;          CHECK_MV16_ZERO;
1018    
1019  // previous frame MV is always possible  // previous frame MV is always possible
1020          CHECK_MV16_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);  
1021            if (!MVzero(prevMB->mvs[0]))
1022            if (!MVequal(prevMB->mvs[0],pmv[0]))
1023                    CHECK_MV16_CANDIDATE(prevMB->mvs[0].x,prevMB->mvs[0].y);
1024    
1025  // left neighbour, if allowed  // left neighbour, if allowed
1026          if (x != 0)  
1027            if (!MVzero(pmv[1]))
1028            if (!MVequal(pmv[1],prevMB->mvs[0]))
1029            if (!MVequal(pmv[1],pmv[0]))
1030          {          {
1031                  if (!(MotionFlags & PMV_HALFPEL16 ))                  if (!(MotionFlags & PMV_HALFPEL16 ))
1032                  {       pmv[1].x = EVEN(pmv[1].x);                  {       pmv[1].x = EVEN(pmv[1].x);
1033                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
1034                  }                  }
1035    
1036                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1037          }          }
1038    
1039  // top neighbour, if allowed  // top neighbour, if allowed
1040          if (y != 0)          if (!MVzero(pmv[2]))
1041            if (!MVequal(pmv[2],prevMB->mvs[0]))
1042            if (!MVequal(pmv[2],pmv[0]))
1043            if (!MVequal(pmv[2],pmv[1]))
1044          {          {
1045                  if (!(MotionFlags & PMV_HALFPEL16 ))                  if (!(MotionFlags & PMV_HALFPEL16 ))
1046                  {       pmv[2].x = EVEN(pmv[2].x);                  {       pmv[2].x = EVEN(pmv[2].x);
# Line 763  Line 1049 
1049                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1050    
1051  // top right neighbour, if allowed  // top right neighbour, if allowed
1052                  if (x != (iWcount-1))                  if (!MVzero(pmv[3]))
1053                    if (!MVequal(pmv[3],prevMB->mvs[0]))
1054                    if (!MVequal(pmv[3],pmv[0]))
1055                    if (!MVequal(pmv[3],pmv[1]))
1056                    if (!MVequal(pmv[3],pmv[2]))
1057                  {                  {
1058                          if (!(MotionFlags & PMV_HALFPEL16 ))                          if (!(MotionFlags & PMV_HALFPEL16 ))
1059                          {       pmv[3].x = EVEN(pmv[3].x);                          {       pmv[3].x = EVEN(pmv[3].x);
# Line 773  Line 1063 
1063                  }                  }
1064          }          }
1065    
1066            if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96)*/ )
1067                    iMinSAD -= MV16_00_BIAS;
1068    
1069    
1070  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
1071     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.
1072  */  */
1073    
1074          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[0]) && (iMinSAD < pMB->sad16) ) )          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[0]) && ((uint32_t)iMinSAD < prevMB->sad16) ) )
1075                  {                  {
1076                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
1077                                  goto step10b;                          goto PMVfast16_Terminate_without_Refine;
1078                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
1079                                  goto step10;                          goto PMVfast16_Terminate_with_Refine;
1080                  }                  }
1081    
1082    
# Line 799  Line 1093 
1093          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1094    
1095  /* 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 */
1096          iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1097                  x, y,                  x, y,
1098                  currMV->x, currMV->y, iMinSAD, &newMV,                  currMV->x, currMV->y, iMinSAD, &newMV,
1099                  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 815  Line 1109 
1109  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1110    
1111                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0],backupMV)) )
1112                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1113                                  x, y,                                  x, y,
1114                          pmv[0].x, pmv[0].y, iMinSAD, &newMV,                          pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1115                          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 828  Line 1122 
1122                  }                  }
1123    
1124                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1125                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1126                                  x, y,                                  x, y,
1127                          0, 0, iMinSAD, &newMV,                          0, 0, iMinSAD, &newMV,
1128                          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 845  Line 1139 
1139          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.
1140  */  */
1141    
1142  step10:  PMVfast16_Terminate_with_Refine:
1143          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
1144                  iMinSAD = PMVfastSearch16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1145                                  x, y,                                  x, y,
1146                                  currMV, iMinSAD,                                  currMV, iMinSAD,
1147                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1148    
1149  step10b:  PMVfast16_Terminate_without_Refine:
1150          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - pmv[0].x;
1151          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - pmv[0].y;
1152          return iMinSAD;          return iMinSAD;
# Line 863  Line 1157 
1157    
1158    
1159    
1160  int32_t PMVfastSearch8_MainSearch(  int32_t Diamond8_MainSearch(
1161                                          const uint8_t * const pRef,                                          const uint8_t * const pRef,
1162                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1163                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
# Line 920  Line 1214 
1214          return iMinSAD;          return iMinSAD;
1215  }  }
1216    
1217  int32_t PMVfastSearch8_Refine(  int32_t Halfpel8_Refine(
1218                                          const uint8_t * const pRef,                                          const uint8_t * const pRef,
1219                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1220                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
# Line 963  Line 1257 
1257                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1258                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1259                                          const int x, const int y,                                          const int x, const int y,
1260                                          const int start_x, int start_y,                                          const int start_x, const int start_y,
1261                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1262                                          MBParam * const pParam,                                          const uint32_t iQuant,
1263                                          MACROBLOCK * const pMBs,                                          const uint32_t iFcode,
1264                                            const MBParam * const pParam,
1265                                            const MACROBLOCK * const pMBs,
1266                                            const MACROBLOCK * const prevMBs,
1267                                          VECTOR * const currMV,                                          VECTOR * const currMV,
1268                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
1269  {  {
1270          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;  
1271          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
1272          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
1273          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
# Line 991  Line 1285 
1285          int32_t psad[4];          int32_t psad[4];
1286          VECTOR newMV;          VECTOR newMV;
1287          VECTOR backupMV;          VECTOR backupMV;
1288            VECTOR startMV;
1289    
1290          MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;  //      const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1291            const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;
1292    
1293          static int32_t threshA,threshB;          static int32_t threshA,threshB;
1294          int32_t iFound,bPredEq;          int32_t iFound,bPredEq;
1295          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
1296    
1297          int32_t iSubBlock = ((y&1)<<1) + (x&1);          int32_t iSubBlock = (y&1)+(y&1) + (x&1);
1298    
1299            /* Init variables */
1300            startMV.x = start_x;
1301            startMV.y = start_y;
1302    
1303  /* Get maximum range */  /* Get maximum range */
1304      get_range(&min_dx, &max_dx, &min_dy, &max_dy,      get_range(&min_dx, &max_dx, &min_dy, &max_dy,
1305                          x, y, 8, iWidth, iHeight, iFcode);                          x, y, 8, iWidth, iHeight, iFcode);
1306    
 /* we work with abs. MVs, not relative to prediction, so range is relative to 0,0 */  
   
1307          if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))          if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))
1308          { min_dx = EVEN(min_dx);          { min_dx = EVEN(min_dx);
1309            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
# Line 1033  Line 1331 
1331    
1332          iFound=0;          iFound=0;
1333    
 /* 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;  
   
1334  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
1335          MinSAD=SAD          MinSAD=SAD
1336          If Motion Vector equal to Previous frame motion vector          If Motion Vector equal to Previous frame motion vector
# Line 1063  Line 1341 
1341    
1342  // Prepare for main loop  // Prepare for main loop
1343    
1344          currMV->x=start_x;              /* start with mv16 */          *currMV = startMV;
         currMV->y=start_y;  
1345    
1346          iMinSAD = sad8( cur,          iMinSAD = sad8( cur,
1347                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),
1348                  iEdgedWidth);                  iEdgedWidth);
1349          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);
1350    
1351          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,pMB->mvs[iSubBlock])) && (iMinSAD < pMB->sad8[iSubBlock]) ) )          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,prevMB->mvs[iSubBlock]))
1352                                    && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )
1353                  {                  {
1354                          if (MotionFlags & PMV_QUICKSTOP8)                  if (MotionFlags & PMV_QUICKSTOP16)
1355                                  goto step10_8b;                          goto PMVfast8_Terminate_without_Refine;
1356                          if (MotionFlags & PMV_EARLYSTOP8)                  if (MotionFlags & PMV_EARLYSTOP16)
1357                                  goto step10_8;                          goto PMVfast8_Terminate_with_Refine;
1358                  }                  }
1359    
1360    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
1361       vector of the median.
1362       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1363    */
1364    
1365            if ((bPredEq) && (MVequal(pmv[0],prevMB->mvs[iSubBlock]) ) )
1366                    iFound=2;
1367    
1368    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
1369       Otherwise select large Diamond Search.
1370    */
1371    
1372            if ( (!MVzero(pmv[0])) || (threshB<1536/4) || (bPredEq) )
1373                    iDiamondSize=1; // 1 halfpel!
1374            else
1375                    iDiamondSize=2; // 2 halfpel = 1 full pixel!
1376    
1377            if (!(MotionFlags & PMV_HALFPELDIAMOND8) )
1378                    iDiamondSize*=2;
1379    
1380    
1381  /*  /*
1382  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.
1383          Also calculate (0,0) but do not subtract offset.          Also calculate (0,0) but do not subtract offset.
1384          Let MinSAD be the smallest SAD up to this point.          Let MinSAD be the smallest SAD up to this point.
1385          If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
1386  */  */
1387    
1388  // the prediction might be even better than mv16  // the median prediction might be even better than mv16
1389    
1390            if (!MVequal(pmv[0],startMV))
1391          CHECK_MV8_CANDIDATE(pmv[0].x,pmv[0].y);          CHECK_MV8_CANDIDATE(pmv[0].x,pmv[0].y);
1392    
1393  // (0,0) is always possible  // (0,0) if needed
1394            if (!MVzero(pmv[0]))
1395            if (!MVzero(startMV))
1396          CHECK_MV8_ZERO;          CHECK_MV8_ZERO;
1397    
1398  // previous frame MV is always possible  // previous frame MV if needed
1399          CHECK_MV8_CANDIDATE(pMB->mvs[iSubBlock].x,pMB->mvs[iSubBlock].y);          if (!MVzero(prevMB->mvs[iSubBlock]))
1400            if (!MVequal(prevMB->mvs[iSubBlock],startMV))
1401            if (!MVequal(prevMB->mvs[iSubBlock],pmv[0]))
1402            CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);
1403    
1404  // left neighbour, if allowed          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[iSubBlock]) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )
1405          if (psad[1] != MV_MAX_ERROR)          {
1406                    if (MotionFlags & PMV_QUICKSTOP16)
1407                            goto PMVfast8_Terminate_without_Refine;
1408                    if (MotionFlags & PMV_EARLYSTOP16)
1409                            goto PMVfast8_Terminate_with_Refine;
1410            }
1411    
1412    
1413    // left neighbour, if allowed and needed
1414            if (!MVzero(pmv[1]))
1415            if (!MVequal(pmv[1],startMV))
1416            if (!MVequal(pmv[1],prevMB->mvs[iSubBlock]))
1417            if (!MVequal(pmv[1],pmv[0]))
1418          {          {
1419                  if (!(MotionFlags & PMV_HALFPEL8 ))                  if (!(MotionFlags & PMV_HALFPEL8 ))
1420                  {       pmv[1].x = EVEN(pmv[1].x);                  {       pmv[1].x = EVEN(pmv[1].x);
# Line 1105  Line 1423 
1423                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
1424          }          }
1425    
1426  // top neighbour, if allowed  // top neighbour, if allowed and needed
1427          if (psad[2] != MV_MAX_ERROR)          if (!MVzero(pmv[2]))
1428            if (!MVequal(pmv[2],startMV))
1429            if (!MVequal(pmv[2],prevMB->mvs[iSubBlock]))
1430            if (!MVequal(pmv[2],pmv[0]))
1431            if (!MVequal(pmv[2],pmv[1]))
1432          {          {
1433                  if (!(MotionFlags & PMV_HALFPEL8 ))                  if (!(MotionFlags & PMV_HALFPEL8 ))
1434                  {       pmv[2].x = EVEN(pmv[2].x);                  {       pmv[2].x = EVEN(pmv[2].x);
# Line 1114  Line 1436 
1436                  }                  }
1437                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
1438    
1439  // top right neighbour, if allowed  // top right neighbour, if allowed and needed
1440                  if (psad[3] != MV_MAX_ERROR)          if (!MVzero(pmv[3]))
1441            if (!MVequal(pmv[3],startMV))
1442            if (!MVequal(pmv[3],prevMB->mvs[iSubBlock]))
1443            if (!MVequal(pmv[3],pmv[0]))
1444            if (!MVequal(pmv[3],pmv[1]))
1445            if (!MVequal(pmv[3],pmv[2]))
1446                  {                  {
1447                  if (!(MotionFlags & PMV_HALFPEL8 ))                  if (!(MotionFlags & PMV_HALFPEL8 ))
1448                  {       pmv[3].x = EVEN(pmv[3].x);                  {       pmv[3].x = EVEN(pmv[3].x);
# Line 1125  Line 1452 
1452                  }                  }
1453          }          }
1454    
1455            if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1456                    iMinSAD -= MV8_00_BIAS;
1457    
1458    
1459  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
1460     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.
1461  */  */
1462    
1463          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]) ) )
1464                  {                  {
1465                          if (MotionFlags & PMV_QUICKSTOP8)                  if (MotionFlags & PMV_QUICKSTOP16)
1466                                  goto step10_8b;                          goto PMVfast8_Terminate_without_Refine;
1467                          if (MotionFlags & PMV_EARLYSTOP8)                  if (MotionFlags & PMV_EARLYSTOP16)
1468                                  goto step10_8;                          goto PMVfast8_Terminate_with_Refine;
1469                  }                  }
1470    
1471  /************ (Diamond Search)  **************/  /************ (Diamond Search)  **************/
# Line 1150  Line 1481 
1481          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1482    
1483  /* 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 */
1484          iSAD = PMVfastSearch8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD = Diamond8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1485                  x, y,                  x, y,
1486                  currMV->x, currMV->y, iMinSAD, &newMV,                  currMV->x, currMV->y, iMinSAD, &newMV,
1487                  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 1166  Line 1497 
1497  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1498    
1499                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0],backupMV)) )
1500                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1501                                  x, y,                                  x, y,
1502                          pmv[0].x, pmv[0].y, iMinSAD, &newMV,                          pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1503                          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 1179  Line 1510 
1510                  }                  }
1511    
1512                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1513                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1514                                  x, y,                                  x, y,
1515                          0, 0, iMinSAD, &newMV,                          0, 0, iMinSAD, &newMV,
1516                          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 1196  Line 1527 
1527           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.
1528  */  */
1529    
1530  step10_8:  PMVfast8_Terminate_with_Refine:
1531          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
1532                  iMinSAD = PMVfastSearch8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1533                                  x, y,                                  x, y,
1534                                  currMV, iMinSAD,                                  currMV, iMinSAD,
1535                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1536    
 step10_8b:  
1537    
1538    PMVfast8_Terminate_without_Refine:
1539          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - pmv[0].x;
1540          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - pmv[0].y;
1541    
1542          return iMinSAD;          return iMinSAD;
1543  }  }
1544    
1545    int32_t EPZSSearch16(
1546                                            const uint8_t * const pRef,
1547                                            const uint8_t * const pRefH,
1548                                            const uint8_t * const pRefV,
1549                                            const uint8_t * const pRefHV,
1550                                            const IMAGE * const pCur,
1551                                            const int x, const int y,
1552                                            const uint32_t MotionFlags,
1553                                            const uint32_t iQuant,
1554                                            const uint32_t iFcode,
1555                                            const MBParam * const pParam,
1556                                            const MACROBLOCK * const pMBs,
1557                                            const MACROBLOCK * const prevMBs,
1558                                            VECTOR * const currMV,
1559                                            VECTOR * const currPMV)
1560    {
1561        const uint32_t iWcount = pParam->mb_width;
1562        const uint32_t iHcount = pParam->mb_height;
1563    
1564            const int32_t iWidth = pParam->width;
1565            const int32_t iHeight = pParam->height;
1566            const int32_t iEdgedWidth = pParam->edged_width;
1567    
1568            const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
1569    
1570            int32_t min_dx;
1571            int32_t max_dx;
1572            int32_t min_dy;
1573            int32_t max_dy;
1574    
1575            VECTOR newMV;
1576            VECTOR backupMV;
1577    
1578            VECTOR pmv[4];
1579            int32_t psad[8];
1580    
1581            static MACROBLOCK * oldMBs = NULL;
1582    //      const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
1583            const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
1584            MACROBLOCK * oldMB = NULL;
1585    
1586            static int32_t thresh2;
1587            int32_t bPredEq;
1588            int32_t iMinSAD,iSAD=9999;
1589    
1590            MainSearch16FuncPtr EPZSMainSearchPtr;
1591    
1592            if (oldMBs == NULL)
1593            {       oldMBs = (MACROBLOCK*) calloc(iWcount*iHcount,sizeof(MACROBLOCK));
1594    //              fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));
1595            }
1596            oldMB = oldMBs + x + y * iWcount;
1597    
1598    /* Get maximum range */
1599            get_range(&min_dx, &max_dx, &min_dy, &max_dy,
1600                            x, y, 16, iWidth, iHeight, iFcode);
1601    
1602            if (!(MotionFlags & PMV_HALFPEL16 ))
1603            { min_dx = EVEN(min_dx);
1604              max_dx = EVEN(max_dx);
1605              min_dy = EVEN(min_dy);
1606              max_dy = EVEN(max_dy);
1607            }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1608    
1609            bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
1610    
1611    /* Step 4: Calculate SAD around the Median prediction.
1612            MinSAD=SAD
1613            If Motion Vector equal to Previous frame motion vector
1614                    and MinSAD<PrevFrmSAD goto Step 10.
1615            If SAD<=256 goto Step 10.
1616    */
1617    
1618    // Prepare for main loop
1619    
1620            *currMV=pmv[0];         /* current best := median prediction */
1621            if (!(MotionFlags & PMV_HALFPEL16))
1622            {
1623                    currMV->x = EVEN(currMV->x);
1624                    currMV->y = EVEN(currMV->y);
1625            }
1626    
1627            if (currMV->x > max_dx)
1628                    currMV->x=max_dx;
1629            if (currMV->x < min_dx)
1630                    currMV->x=min_dx;
1631            if (currMV->y > max_dy)
1632                    currMV->y=max_dy;
1633            if (currMV->y < min_dy)
1634                    currMV->y=min_dy;
1635    
1636    /***************** This is predictor SET A: only median prediction ******************/
1637    
1638            iMinSAD = sad16( cur,
1639                    get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),
1640                    iEdgedWidth, MV_MAX_ERROR);
1641            iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);
1642    
1643    // thresh1 is fixed to 256
1644            if ( (iMinSAD < 256 ) || ( (MVequal(*currMV, prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )
1645                    {
1646                            if (MotionFlags & PMV_QUICKSTOP16)
1647                                    goto EPZS16_Terminate_without_Refine;
1648                            if (MotionFlags & PMV_EARLYSTOP16)
1649                                    goto EPZS16_Terminate_with_Refine;
1650                    }
1651    
1652    /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
1653    
1654    // previous frame MV
1655            CHECK_MV16_CANDIDATE(prevMB->mvs[0].x,prevMB->mvs[0].y);
1656    
1657    // set threshhold based on Min of Prediction and SAD of collocated block
1658    // CHECK_MV16 always uses iSAD for the SAD of last vector to check, so now iSAD is what we want
1659    
1660            if ((x==0) && (y==0) )
1661            {
1662                    thresh2 =  512;
1663            }
1664            else
1665            {
1666    /* T_k = 1.2 * MIN(SAD_top,SAD_left,SAD_topleft,SAD_coll) +128;   [Tourapis, 2002] */
1667    
1668                    thresh2 = MIN(psad[0],iSAD)*6/5 + 128;
1669            }
1670    
1671    // MV=(0,0) is often a good choice
1672    
1673            CHECK_MV16_ZERO;
1674    
1675    
1676    // left neighbour, if allowed
1677            if (x != 0)
1678            {
1679                    if (!(MotionFlags & PMV_HALFPEL16 ))
1680                    {       pmv[1].x = EVEN(pmv[1].x);
1681                            pmv[1].y = EVEN(pmv[1].y);
1682                    }
1683                    CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1684            }
1685    
1686    // top neighbour, if allowed
1687            if (y != 0)
1688            {
1689                    if (!(MotionFlags & PMV_HALFPEL16 ))
1690                    {       pmv[2].x = EVEN(pmv[2].x);
1691                            pmv[2].y = EVEN(pmv[2].y);
1692                    }
1693                    CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1694    
1695    // top right neighbour, if allowed
1696                    if ((uint32_t)x != (iWcount-1))
1697                    {
1698                            if (!(MotionFlags & PMV_HALFPEL16 ))
1699                            {       pmv[3].x = EVEN(pmv[3].x);
1700                                    pmv[3].y = EVEN(pmv[3].y);
1701                            }
1702                            CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);
1703                    }
1704            }
1705    
1706    /* Terminate if MinSAD <= T_2
1707       Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
1708    */
1709    
1710            if ( (iMinSAD <= thresh2)
1711                    || ( MVequal(*currMV,prevMB->mvs[0]) && ((uint32_t)iMinSAD <= prevMB->sad16) ) )
1712                    {
1713                            if (MotionFlags & PMV_QUICKSTOP16)
1714                                    goto EPZS16_Terminate_without_Refine;
1715                            if (MotionFlags & PMV_EARLYSTOP16)
1716                                    goto EPZS16_Terminate_with_Refine;
1717                    }
1718    
1719    /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/
1720    
1721            backupMV = prevMB->mvs[0];              // collocated MV
1722            backupMV.x += (prevMB->mvs[0].x - oldMB->mvs[0].x );    // acceleration X
1723            backupMV.y += (prevMB->mvs[0].y - oldMB->mvs[0].y );    // acceleration Y
1724    
1725            CHECK_MV16_CANDIDATE(backupMV.x,backupMV.y);
1726    
1727    // left neighbour
1728            if (x != 0)
1729                    CHECK_MV16_CANDIDATE((prevMB-1)->mvs[0].x,(prevMB-1)->mvs[0].y);
1730    
1731    // top neighbour
1732            if (y != 0)
1733                    CHECK_MV16_CANDIDATE((prevMB-iWcount)->mvs[0].x,(prevMB-iWcount)->mvs[0].y);
1734    
1735    // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs
1736    
1737            if ((uint32_t)x != iWcount-1)
1738                    CHECK_MV16_CANDIDATE((prevMB+1)->mvs[0].x,(prevMB+1)->mvs[0].y);
1739    
1740    // bottom neighbour, dito
1741            if ((uint32_t)y != iHcount-1)
1742                    CHECK_MV16_CANDIDATE((prevMB+iWcount)->mvs[0].x,(prevMB+iWcount)->mvs[0].y);
1743    
1744    /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */
1745            if (iMinSAD <= thresh2)
1746                    {
1747                            if (MotionFlags & PMV_QUICKSTOP16)
1748                                    goto EPZS16_Terminate_without_Refine;
1749                            if (MotionFlags & PMV_EARLYSTOP16)
1750                                    goto EPZS16_Terminate_with_Refine;
1751                    }
1752    
1753    /************ (if Diamond Search)  **************/
1754    
1755            backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1756    
1757    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
1758    
1759            if (MotionFlags & PMV_USESQUARES16)
1760                    EPZSMainSearchPtr = Square16_MainSearch;
1761            else
1762                    EPZSMainSearchPtr = Diamond16_MainSearch;
1763    
1764            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1765                            x, y,
1766                            currMV->x, currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1767                            2, iFcode, iQuant, 0);
1768    
1769            if (iSAD < iMinSAD)
1770            {
1771                    *currMV = newMV;
1772                    iMinSAD = iSAD;
1773            }
1774    
1775    
1776            if (MotionFlags & PMV_EXTSEARCH16)
1777            {
1778    /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
1779    
1780                    if (!(MVequal(pmv[0],backupMV)) )
1781                    {
1782                            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1783                                    x, y,
1784                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1785                                    pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
1786                    }
1787    
1788                    if (iSAD < iMinSAD)
1789                    {
1790                            *currMV = newMV;
1791                            iMinSAD = iSAD;
1792                    }
1793    
1794                    if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1795                    {
1796                            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1797                                    x, y,
1798                            0, 0, iMinSAD, &newMV,
1799                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
1800    
1801                            if (iSAD < iMinSAD)
1802                            {
1803                                    *currMV = newMV;
1804                                    iMinSAD = iSAD;
1805                            }
1806                    }
1807            }
1808    
1809    /***************        Choose best MV found     **************/
1810    
1811    EPZS16_Terminate_with_Refine:
1812            if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
1813                    iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1814                                    x, y,
1815                                    currMV, iMinSAD,
1816                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1817    
1818    EPZS16_Terminate_without_Refine:
1819    
1820            *oldMB = *prevMB;
1821    
1822            currPMV->x = currMV->x - pmv[0].x;
1823            currPMV->y = currMV->y - pmv[0].y;
1824            return iMinSAD;
1825    }
1826    
1827    
1828    int32_t EPZSSearch8(
1829                                            const uint8_t * const pRef,
1830                                            const uint8_t * const pRefH,
1831                                            const uint8_t * const pRefV,
1832                                            const uint8_t * const pRefHV,
1833                                            const IMAGE * const pCur,
1834                                            const int x, const int y,
1835                                            const int start_x, const int start_y,
1836                                            const uint32_t MotionFlags,
1837                                            const uint32_t iQuant,
1838                                            const uint32_t iFcode,
1839                                            const MBParam * const pParam,
1840                                            const MACROBLOCK * const pMBs,
1841                                            const MACROBLOCK * const prevMBs,
1842                                            VECTOR * const currMV,
1843                                            VECTOR * const currPMV)
1844    {
1845    /* Please not that EPZS might not be a good choice for 8x8-block motion search ! */
1846    
1847            const uint32_t iWcount = pParam->mb_width;
1848            const int32_t iWidth = pParam->width;
1849            const int32_t iHeight = pParam->height;
1850            const int32_t iEdgedWidth = pParam->edged_width;
1851    
1852            const uint8_t * cur = pCur->y + x*8 + y*8*iEdgedWidth;
1853    
1854            int32_t iDiamondSize=1;
1855    
1856            int32_t min_dx;
1857            int32_t max_dx;
1858            int32_t min_dy;
1859            int32_t max_dy;
1860    
1861            VECTOR newMV;
1862            VECTOR backupMV;
1863    
1864            VECTOR pmv[4];
1865            int32_t psad[8];
1866    
1867            const   int32_t iSubBlock = ((y&1)<<1) + (x&1);
1868    
1869    //      const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1870            const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;
1871    
1872            int32_t bPredEq;
1873            int32_t iMinSAD,iSAD=9999;
1874    
1875            MainSearch8FuncPtr EPZSMainSearchPtr;
1876    
1877    /* Get maximum range */
1878            get_range(&min_dx, &max_dx, &min_dy, &max_dy,
1879                            x, y, 8, iWidth, iHeight, iFcode);
1880    
1881    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
1882    
1883            if (!(MotionFlags & PMV_HALFPEL8 ))
1884            { min_dx = EVEN(min_dx);
1885              max_dx = EVEN(max_dx);
1886              min_dy = EVEN(min_dy);
1887              max_dy = EVEN(max_dy);
1888            }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1889    
1890            bPredEq  = get_pmvdata(pMBs, x>>1, y>>1, iWcount, iSubBlock, pmv, psad);
1891    
1892    
1893    /* Step 4: Calculate SAD around the Median prediction.
1894            MinSAD=SAD
1895            If Motion Vector equal to Previous frame motion vector
1896                    and MinSAD<PrevFrmSAD goto Step 10.
1897            If SAD<=256 goto Step 10.
1898    */
1899    
1900    // Prepare for main loop
1901    
1902    
1903            if (!(MotionFlags & PMV_HALFPEL8))
1904            {
1905                    currMV->x = EVEN(currMV->x);
1906                    currMV->y = EVEN(currMV->y);
1907            }
1908    
1909            if (currMV->x > max_dx)
1910                    currMV->x=max_dx;
1911            if (currMV->x < min_dx)
1912                    currMV->x=min_dx;
1913            if (currMV->y > max_dy)
1914                    currMV->y=max_dy;
1915            if (currMV->y < min_dy)
1916                    currMV->y=min_dy;
1917    
1918    /***************** This is predictor SET A: only median prediction ******************/
1919    
1920    
1921            iMinSAD = sad8( cur,
1922                    get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),
1923                    iEdgedWidth);
1924            iMinSAD += calc_delta_8(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);
1925    
1926    
1927    // thresh1 is fixed to 256
1928            if (iMinSAD < 256/4 )
1929                    {
1930                            if (MotionFlags & PMV_QUICKSTOP8)
1931                                    goto EPZS8_Terminate_without_Refine;
1932                            if (MotionFlags & PMV_EARLYSTOP8)
1933                                    goto EPZS8_Terminate_with_Refine;
1934                    }
1935    
1936    /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
1937    
1938    
1939    // MV=(0,0) is often a good choice
1940            CHECK_MV8_ZERO;
1941    
1942    // previous frame MV
1943            CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);
1944    
1945    // left neighbour, if allowed
1946            if (psad[1] != MV_MAX_ERROR)
1947            {
1948                    if (!(MotionFlags & PMV_HALFPEL8 ))
1949                    {       pmv[1].x = EVEN(pmv[1].x);
1950                            pmv[1].y = EVEN(pmv[1].y);
1951                    }
1952                    CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
1953            }
1954    
1955    // top neighbour, if allowed
1956            if (psad[2] != MV_MAX_ERROR)
1957            {
1958                    if (!(MotionFlags & PMV_HALFPEL8 ))
1959                    {       pmv[2].x = EVEN(pmv[2].x);
1960                            pmv[2].y = EVEN(pmv[2].y);
1961                    }
1962                    CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
1963    
1964    // top right neighbour, if allowed
1965                    if (psad[3] != MV_MAX_ERROR)
1966                    {
1967                            if (!(MotionFlags & PMV_HALFPEL8 ))
1968                            {       pmv[3].x = EVEN(pmv[3].x);
1969                                    pmv[3].y = EVEN(pmv[3].y);
1970                            }
1971                            CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);
1972                    }
1973            }
1974    
1975    /*  // this bias is zero anyway, at the moment!
1976    
1977            if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) ) // && (iMinSAD <= iQuant * 96)
1978                    iMinSAD -= MV8_00_BIAS;
1979    
1980    */
1981    
1982    /* Terminate if MinSAD <= T_2
1983       Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
1984    */
1985    
1986            if (iMinSAD < 512/4)    /* T_2 == 512/4 hardcoded */
1987                    {
1988                            if (MotionFlags & PMV_QUICKSTOP8)
1989                                    goto EPZS8_Terminate_without_Refine;
1990                            if (MotionFlags & PMV_EARLYSTOP8)
1991                                    goto EPZS8_Terminate_with_Refine;
1992                    }
1993    
1994    /************ (Diamond Search)  **************/
1995    
1996            backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1997    
1998            if (!(MotionFlags & PMV_HALFPELDIAMOND8))
1999                    iDiamondSize *= 2;
2000    
2001    /* default: use best prediction as starting point for one call of EPZS_MainSearch */
2002    
2003    /* // there is no EPZS^2 for inter4v at the moment
2004    
2005            if (MotionFlags & PMV_USESQUARES8)
2006                    EPZSMainSearchPtr = Square8_MainSearch;
2007            else
2008    */
2009    
2010            EPZSMainSearchPtr = Diamond8_MainSearch;
2011    
2012            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
2013                    x, y,
2014                    currMV->x, currMV->y, iMinSAD, &newMV,
2015                    pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2016                    iDiamondSize, iFcode, iQuant, 0);
2017    
2018    
2019            if (iSAD < iMinSAD)
2020            {
2021                    *currMV = newMV;
2022                    iMinSAD = iSAD;
2023            }
2024    
2025            if (MotionFlags & PMV_EXTSEARCH8)
2026            {
2027    /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
2028    
2029                    if (!(MVequal(pmv[0],backupMV)) )
2030                    {
2031                            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
2032                                    x, y,
2033                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,
2034                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);
2035    
2036                            if (iSAD < iMinSAD)
2037                            {
2038                                    *currMV = newMV;
2039                                    iMinSAD = iSAD;
2040                            }
2041                    }
2042    
2043                    if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
2044                    {
2045                            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
2046                                    x, y,
2047                            0, 0, iMinSAD, &newMV,
2048                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);
2049    
2050                            if (iSAD < iMinSAD)
2051                            {
2052                                    *currMV = newMV;
2053                                    iMinSAD = iSAD;
2054                            }
2055                    }
2056            }
2057    
2058    /***************        Choose best MV found     **************/
2059    
2060    EPZS8_Terminate_with_Refine:
2061            if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
2062                    iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,
2063                                    x, y,
2064                                    currMV, iMinSAD,
2065                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
2066    
2067    EPZS8_Terminate_without_Refine:
2068    
2069            currPMV->x = currMV->x - pmv[0].x;
2070            currPMV->y = currMV->y - pmv[0].y;
2071            return iMinSAD;
2072    }
2073    
2074    
2075    
2076    
2077    
2078    /* ***********************************************************
2079            bvop motion estimation
2080    // TODO: need to incorporate prediction here (eg. sad += calc_delta_16)
2081    ***************************************************************/
2082    
2083    
2084    void MotionEstimationBVOP(
2085                            MBParam * const pParam,
2086                            FRAMEINFO * const frame,
2087    
2088                            // forward (past) reference
2089                            const MACROBLOCK * const f_mbs,
2090                        const IMAGE * const f_ref,
2091                            const IMAGE * const f_refH,
2092                        const IMAGE * const f_refV,
2093                            const IMAGE * const f_refHV,
2094                            // backward (future) reference
2095                            const MACROBLOCK * const b_mbs,
2096                        const IMAGE * const b_ref,
2097                            const IMAGE * const b_refH,
2098                        const IMAGE * const b_refV,
2099                            const IMAGE * const b_refHV)
2100    {
2101        const uint32_t mb_width = pParam->mb_width;
2102        const uint32_t mb_height = pParam->mb_height;
2103            const int32_t edged_width = pParam->edged_width;
2104    
2105            uint32_t i,j;
2106    
2107            int32_t f_sad16;
2108            int32_t b_sad16;
2109            int32_t i_sad16;
2110            int32_t d_sad16;
2111            int32_t best_sad;
2112    
2113            VECTOR pmv_dontcare;
2114    
2115            // note: i==horizontal, j==vertical
2116        for (j = 0; j < mb_height; j++)
2117            {
2118                    for (i = 0; i < mb_width; i++)
2119                    {
2120                            MACROBLOCK *mb = &frame->mbs[i + j*mb_width];
2121                            const MACROBLOCK *f_mb = &f_mbs[i + j*mb_width];
2122                            const MACROBLOCK *b_mb = &b_mbs[i + j*mb_width];
2123    
2124                            if (b_mb->mode == MODE_INTER
2125                                    && b_mb->cbp == 0
2126                                    && b_mb->mvs[0].x == 0
2127                                    && b_mb->mvs[0].y == 0)
2128                            {
2129                                    mb->mode = MODE_NOT_CODED;
2130                                    mb->mvs[0].x = 0;
2131                                    mb->mvs[0].y = 0;
2132                                    mb->b_mvs[0].x = 0;
2133                                    mb->b_mvs[0].y = 0;
2134                                    continue;
2135                            }
2136    
2137    
2138                            // forward search
2139                            f_sad16 = SEARCH16(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2140                                                    &frame->image,
2141                                                    i, j,
2142                                                    frame->motion_flags,  frame->quant, frame->fcode,
2143                                                    pParam,
2144                                                    f_mbs, f_mbs /* todo */,
2145                                                    &mb->mvs[0], &pmv_dontcare);    // ignore pmv
2146    
2147                            // backward search
2148                            b_sad16 = SEARCH16(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
2149                                                    &frame->image,
2150                                                    i, j,
2151                                                    frame->motion_flags,  frame->quant, frame->bcode,
2152                                                    pParam,
2153                                                    b_mbs, b_mbs, /* todo */
2154                                                    &mb->b_mvs[0], &pmv_dontcare);  // ignore pmv
2155    
2156                            // interpolate search (simple, but effective)
2157                            i_sad16 = sad16bi_c(
2158                                            frame->image.y + i*16 + j*16*edged_width,
2159                                            get_ref(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2160                                                    i, j, 16, mb->mvs[0].x, mb->mvs[0].y, edged_width),
2161                                            get_ref(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
2162                                                    i, j, 16, mb->b_mvs[0].x, mb->b_mvs[0].x, edged_width),
2163                                            edged_width);
2164    
2165                            // TODO: direct search
2166                            // predictor + range of [-32,32]
2167                            d_sad16 = 65535;
2168    
2169    
2170                            if (f_sad16 < b_sad16)
2171                            {
2172                                    best_sad = f_sad16;
2173                                    mb->mode = MODE_FORWARD;
2174                            }
2175                            else
2176                            {
2177                                    best_sad = b_sad16;
2178                                    mb->mode = MODE_BACKWARD;
2179                            }
2180    
2181                            if (i_sad16 < best_sad)
2182                            {
2183                                    best_sad = i_sad16;
2184                                    mb->mode = MODE_INTERPOLATE;
2185                            }
2186    
2187                            if (d_sad16 < best_sad)
2188                            {
2189                                    best_sad = d_sad16;
2190                                    mb->mode = MODE_DIRECT;
2191                            }
2192    
2193                    }
2194            }
2195    }

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

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