[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 117, Thu Apr 11 15:04:05 2002 UTC revision 174, Sat May 11 23:54:30 2002 UTC
# Line 2  Line 2 
2   *   *
3   *  Modifications:   *  Modifications:
4   *   *
5     *      01.05.2002      updated MotionEstimationBVOP
6     *      25.04.2002 partial prevMB conversion
7     *  22.04.2002 remove some compile warning by chenm001 <chenm001@163.com>
8     *  14.04.2002 added MotionEstimationBVOP()
9   *  02.04.2002 add EPZS(^2) as ME algorithm, use PMV_USESQUARES to choose between   *  02.04.2002 add EPZS(^2) as ME algorithm, use PMV_USESQUARES to choose between
10   *             EPZS and EPZS^2   *             EPZS and EPZS^2
11   *  08.02.2002 split up PMVfast into three routines: PMVFast, PMVFast_MainLoop   *  08.02.2002 split up PMVfast into three routines: PMVFast, PMVFast_MainLoop
# Line 40  Line 44 
44  #include "../prediction/mbprediction.h"  #include "../prediction/mbprediction.h"
45  #include "../global.h"  #include "../global.h"
46  #include "../utils/timer.h"  #include "../utils/timer.h"
47    #include "motion.h"
48  #include "sad.h"  #include "sad.h"
49    
50  // very large value  // very large value
# Line 49  Line 54 
54  #define MV16_THRESHOLD  192  #define MV16_THRESHOLD  192
55  #define MV8_THRESHOLD   56  #define MV8_THRESHOLD   56
56    
57    #define NEIGH_MOVE_THRESH 8
58    // how much a block's MV must differ from his neighbour
59    // to be search for INTER4V. The more, the faster...
60    
61  /* sad16(0,0) bias; mpeg4 spec suggests nb/2+1 */  /* sad16(0,0) bias; mpeg4 spec suggests nb/2+1 */
62  /* nb  = vop pixels * 2^(bpp-8) */  /* nb  = vop pixels * 2^(bpp-8) */
63  #define MV16_00_BIAS    (128+1)  #define MV16_00_BIAS    (128+1)
64    #define MV8_00_BIAS     (0)
65    
66  /* INTER bias for INTER/INTRA decision; mpeg4 spec suggests 2*nb */  /* INTER bias for INTER/INTRA decision; mpeg4 spec suggests 2*nb */
67  #define INTER_BIAS      512  #define MV16_INTER_BIAS 512
68    
69  /* Parameters which control inter/inter4v decision */  /* Parameters which control inter/inter4v decision */
70  #define IMV16X16                        5  #define IMV16X16                        5
# Line 63  Line 73 
73  #define NEIGH_TEND_16X16        2  #define NEIGH_TEND_16X16        2
74  #define NEIGH_TEND_8X8          2  #define NEIGH_TEND_8X8          2
75    
   
76  // fast ((A)/2)*2  // fast ((A)/2)*2
77  #define EVEN(A)         (((A)<0?(A)+1:(A)) & ~1)  #define EVEN(A)         (((A)<0?(A)+1:(A)) & ~1)
78    
79    #define MVzero(A) ( ((A).x)==(0) && ((A).y)==(0) )
80  #define MIN(X, Y) ((X)<(Y)?(X):(Y))  #define MVequal(A,B) ( ((A).x)==((B).x) && ((A).y)==((B).y) )
 #define MAX(X, Y) ((X)>(Y)?(X):(Y))  
 #define ABS(X)    (((X)>0)?(X):-(X))  
 #define SIGN(X)   (((X)>0)?1:-1)  
81    
82  int32_t PMVfastSearch16(  int32_t PMVfastSearch16(
83                                          const uint8_t * const pRef,                                          const uint8_t * const pRef,
# Line 81  Line 87 
87                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
88                                          const int x, const int y,                                          const int x, const int y,
89                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
90                                            const uint32_t iQuant,
91                                            const uint32_t iFcode,
92                                          const MBParam * const pParam,                                          const MBParam * const pParam,
93                                          MACROBLOCK * const pMBs,                                          const MACROBLOCK * const pMBs,
94                                            const MACROBLOCK * const prevMBs,
95                                          VECTOR * const currMV,                                          VECTOR * const currMV,
96                                          VECTOR * const currPMV);                                          VECTOR * const currPMV);
97    
# Line 94  Line 103 
103                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
104                                          const int x, const int y,                                          const int x, const int y,
105                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
106                                            const uint32_t iQuant,
107                                            const uint32_t iFcode,
108                                          const MBParam * const pParam,                                          const MBParam * const pParam,
109                                          MACROBLOCK * const pMBs,                                          const MACROBLOCK * const pMBs,
110                                            const MACROBLOCK * const prevMBs,
111                                          VECTOR * const currMV,                                          VECTOR * const currMV,
112                                          VECTOR * const currPMV);                                          VECTOR * const currPMV);
113    
# Line 107  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 MotionFlags,                                          const uint32_t MotionFlags,
124                                            const uint32_t iQuant,
125                                            const uint32_t iFcode,
126                                          const MBParam * const pParam,                                          const MBParam * const pParam,
127                                          MACROBLOCK * const pMBs,                                          const MACROBLOCK * const pMBs,
128                                            const MACROBLOCK * const prevMBs,
129                                          VECTOR * const currMV,                                          VECTOR * const currMV,
130                                          VECTOR * const currPMV);                                          VECTOR * const currPMV);
131    
# Line 121  Line 136 
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 int start_x, int start_y,                                          const int start_x, const int start_y,
140                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
141                                            const uint32_t iQuant,
142                                            const uint32_t iFcode,
143                                          const MBParam * const pParam,                                          const MBParam * const pParam,
144                                          MACROBLOCK * const pMBs,                                          const MACROBLOCK * const pMBs,
145                                            const MACROBLOCK * const prevMBs,
146                                          VECTOR * const currMV,                                          VECTOR * const currMV,
147                                          VECTOR * const currPMV);                                          VECTOR * const currPMV);
148    
# Line 172  Line 190 
190    
191  typedef MainSearch8Func* MainSearch8FuncPtr;  typedef MainSearch8Func* MainSearch8FuncPtr;
192    
193    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            (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    
204    
205    
206  // mv.length table  // mv.length table
207  static const uint32_t mvtab[33] = {  static const uint32_t mvtab[33] = {
208      1,  2,  3,  4,  6,  7,  7,  7,      1,  2,  3,  4,  6,  7,  7,  7,
# Line 207  Line 238 
238  }  }
239    
240    
241  static __inline uint32_t calc_delta_16(const int32_t dx, const int32_t dy, const uint32_t iFcode)  static __inline uint32_t calc_delta_16(const int32_t dx, const int32_t dy, const uint32_t iFcode, const uint32_t iQuant)
 {  
         return NEIGH_TEND_16X16 * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));  
 }  
   
 static __inline uint32_t calc_delta_8(const int32_t dx, const int32_t dy, const uint32_t iFcode)  
   
242  {  {
243      return NEIGH_TEND_8X8 * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));          return NEIGH_TEND_16X16 * lambda_vec16[iQuant] * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));
244  }  }
245    
246    static __inline uint32_t calc_delta_8(const int32_t dx, const int32_t dy, const uint32_t iFcode, const uint32_t iQuant)
247    
   
   
 /* calculate the min/max range (in halfpixels)  
         relative to the _MACROBLOCK_ position  
 */  
   
 static void __inline get_range(  
         int32_t * const min_dx, int32_t * const max_dx,  
         int32_t * const min_dy, int32_t * const max_dy,  
         const uint32_t x, const uint32_t y,  
         const uint32_t block_sz,                                        // block dimension, 8 or 16  
         const uint32_t width, const uint32_t height,  
         const uint32_t fcode)  
248  {  {
249        return NEIGH_TEND_8X8 * lambda_vec8[iQuant] * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));
         const int search_range = 32 << (fcode - 1);  
         const int high = search_range - 1;  
         const int low = -search_range;  
   
         // convert full-pixel measurements to half pixel  
         const int hp_width = 2 * width;  
         const int hp_height = 2 * height;  
         const int hp_edge = 2 * block_sz;  
         const int hp_x = 2 * (x) * block_sz;            // we need _right end_ of block, not x-coordinate  
         const int hp_y = 2 * (y) * block_sz;            // same for _bottom end_  
   
         *max_dx = MIN(high,     hp_width - hp_x);  
         *max_dy = MIN(high,     hp_height - hp_y);  
         *min_dx = MAX(low,      -(hp_edge + hp_x));  
         *min_dy = MAX(low,      -(hp_edge + hp_y));  
   
 }  
   
   
 /*  
  * getref: calculate reference image pointer  
  * the decision to use interpolation h/v/hv or the normal image is  
  * based on dx & dy.  
  */  
   
 static __inline const uint8_t * get_ref(  
         const uint8_t * const refn,  
         const uint8_t * const refh,  
         const uint8_t * const refv,  
         const uint8_t * const refhv,  
         const uint32_t x, const uint32_t y,  
         const uint32_t block,                                   // block dimension, 8 or 16  
         const int32_t dx, const int32_t dy,  
         const uint32_t stride)  
 {  
   
         switch ( ((dx&1)<<1) + (dy&1) )         // ((dx%2)?2:0)+((dy%2)?1:0)  
         {  
         case 0  : return refn + (x*block+dx/2) + (y*block+dy/2)*stride;  
         case 1  : return refv + (x*block+dx/2) + (y*block+(dy-1)/2)*stride;  
         case 2  : return refh + (x*block+(dx-1)/2) + (y*block+dy/2)*stride;  
         default :  
         case 3  : return refhv + (x*block+(dx-1)/2) + (y*block+(dy-1)/2)*stride;  
         }  
   
250  }  }
251    
252    
 /* This is somehow a copy of get_ref, but with MV instead of X,Y */  
   
 static __inline const uint8_t * get_ref_mv(  
         const uint8_t * const refn,  
         const uint8_t * const refh,  
         const uint8_t * const refv,  
         const uint8_t * const refhv,  
         const uint32_t x, const uint32_t y,  
         const uint32_t block,                   // block dimension, 8 or 16  
         const VECTOR* mv,       // measured in half-pel!  
         const uint32_t stride)  
 {  
253    
         switch ( (((mv->x)&1)<<1) + ((mv->y)&1) )  
         {  
         case 0  : return refn + (x*block+(mv->x)/2) + (y*block+(mv->y)/2)*stride;  
         case 1  : return refv + (x*block+(mv->x)/2) + (y*block+((mv->y)-1)/2)*stride;  
         case 2  : return refh + (x*block+((mv->x)-1)/2) + (y*block+(mv->y)/2)*stride;  
         default :  
         case 3  : return refhv + (x*block+((mv->x)-1)/2) + (y*block+((mv->y)-1)/2)*stride;  
         }  
254    
 }  
255    
256  #ifndef SEARCH16  #ifndef SEARCH16
257  #define SEARCH16        PMVfastSearch16  #define SEARCH16        PMVfastSearch16
# Line 318  Line 265 
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          if (sadInit)          if (sadInit)
292                  (*sadInit)();                  (*sadInit)();
293    
294          // note: i==horizontal, j==vertical          for (y = 0; y < iHcount; y++)
295          for (i = 0; i < iHcount; i++)                  for (x = 0; x < iWcount; x++)
                 for (j = 0; j < iWcount; j++)  
296                  {                  {
297                          MACROBLOCK *pMB = &pMBs[j + i * iWcount];                          MACROBLOCK* const pMB = &pMBs[x + y * iWcount];
   
                         sad16 = SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,  
                                          j, i, pParam->motion_flags,  
                                          pParam, pMBs, &mv16, &pmv16);  
                         pMB->sad16=sad16;  
298    
299                            pMB->sad16 = SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
300                                             x, y, current->motion_flags, current->quant, current->fcode,
301                                             pParam, pMBs, prevMBs, &pMB->mv16, &pMB->pmvs[0]);
302                    }
303    
304                          /* decide: MODE_INTER or MODE_INTRA          for (y = 0; y < iHcount; y++)
305                             if (dev_intra < sad_inter - 2 * nb) use_intra                  for (x = 0; x < iWcount; x++)
306                          */                  {
307                            MACROBLOCK* const pMB = &pMBs[x + y * iWcount];
308    
309                          deviation = dev16(pCurrent->y + j*16 + i*16*pParam->edged_width, pParam->edged_width);                          if (0 < (pMB->sad16 - MV16_INTER_BIAS))
310                            {
311                                    int32_t deviation;
312                                    deviation = dev16(pCurrent->y + x*16 + y*16*pParam->edged_width,
313                                                             pParam->edged_width);
314    
315                          if (deviation < (sad16 - INTER_BIAS))                                  if (deviation < (pMB->sad16 - MV16_INTER_BIAS))
316                          {                          {
317                                  pMB->mode = MODE_INTRA;                                  pMB->mode = MODE_INTRA;
318                                  pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = 0;                                          pMB->mv16 = pMB->mvs[0] = pMB->mvs[1]
319                                  pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = 0;                                                                   = pMB->mvs[2] = pMB->mvs[3] = zeroMV;
320                                            pMB->sad16 = pMB->sad8[0] = pMB->sad8[1]
321                                                                 = pMB->sad8[2] = pMB->sad8[3] = 0;
322    
323                                  iIntra++;                                  iIntra++;
324                                  if(iIntra >= iLimit)                                  if(iIntra >= iLimit)
# Line 373  Line 326 
326    
327                                  continue;                                  continue;
328                          }                          }
   
                         if (pParam->global_flags & XVID_INTER4V)  
                         {  
                                 pMB->sad8[0] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,  
                                                        2 * j, 2 * i, mv16.x, mv16.y, pParam->motion_flags,  
                                                        pParam, pMBs, &pMB->mvs[0], &pMB->pmvs[0]);  
   
                                 pMB->sad8[1] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,  
                                                        2 * j + 1, 2 * i, mv16.x, mv16.y, pParam->motion_flags,  
                                                        pParam, pMBs, &pMB->mvs[1], &pMB->pmvs[1]);  
   
                                 pMB->sad8[2] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,  
                                                        2 * j, 2 * i + 1, mv16.x, mv16.y, pParam->motion_flags,  
                                                        pParam, pMBs, &pMB->mvs[2], &pMB->pmvs[2]);  
   
                                 pMB->sad8[3] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,  
                                                        2 * j + 1, 2 * i + 1, mv16.x, mv16.y, pParam->motion_flags,  
                                                        pParam, pMBs, &pMB->mvs[3], &pMB->pmvs[3]);  
   
                                 sad8 = pMB->sad8[0] + pMB->sad8[1] + pMB->sad8[2] + pMB->sad8[3];  
329                          }                          }
330    
331                            if ( (current->global_flags & XVID_INTER4V)
332                                    && (!(current->global_flags & XVID_LUMIMASKING)
333                                            || pMB->dquant == NO_CHANGE) )
334                            {
335                                    int32_t neigh=0;
336    
337                                    if (x>0)
338                                    {       neigh += abs((pMB->mv16.x)-((pMB-1)->mv16.x));
339                                            neigh += abs((pMB->mv16.y)-((pMB-1)->mv16.y));
340                                    }
341                                    if (y>0)
342                                    {       neigh += abs((pMB->mv16.x)-((pMB-iWcount)->mv16.x));
343                                            neigh += abs((pMB->mv16.y)-((pMB-iWcount)->mv16.y));
344                                    }
345                                    if (x<(iWcount-1))
346                                    {       neigh += abs((pMB->mv16.x)-((pMB+1)->mv16.x));
347                                            neigh += abs((pMB->mv16.y)-((pMB+1)->mv16.y));
348                                    }
349                                    if (y<(iHcount-1))
350                                    {       neigh += abs((pMB->mv16.x)-((pMB+iHcount)->mv16.x));
351                                            neigh += abs((pMB->mv16.y)-((pMB+iHcount)->mv16.y));
352                                    }
353    
354                                    if (neigh > NEIGH_MOVE_THRESH)
355                                    {
356                                            int32_t sad8 = 129; //IMV16X16 * current->quant;
357    
358                                    if (sad8 < pMB->sad16)
359                                    sad8 += pMB->sad8[0]
360                                            = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
361                                                           2*x, 2*y, pMB->mv16.x, pMB->mv16.y,
362                                                               current->motion_flags, current->quant, current->fcode,
363                                                           pParam, pMBs, prevMBs, &pMB->mvs[0], &pMB->pmvs[0]);
364    
365                                    if (sad8 < pMB->sad16)
366                                    sad8 += pMB->sad8[1]
367                                            = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
368                                   2*x+1, 2*y, pMB->mv16.x, pMB->mv16.y,
369                                                    current->motion_flags, current->quant, current->fcode,
370                                                    pParam, pMBs, prevMBs, &pMB->mvs[1], &pMB->pmvs[1]);
371    
372                                    if (sad8 < pMB->sad16)
373                                    sad8 += pMB->sad8[2]
374                                            = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
375                                                    2*x, 2*y+1, pMB->mv16.x, pMB->mv16.y,
376                                                    current->motion_flags, current->quant, current->fcode,
377                                                    pParam, pMBs, prevMBs, &pMB->mvs[2], &pMB->pmvs[2]);
378    
379                                    if (sad8 < pMB->sad16)
380                                    sad8 += pMB->sad8[3]
381                                            = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
382                                                    2*x+1, 2*y+1, pMB->mv16.x, pMB->mv16.y,
383                                                    current->motion_flags, current->quant, current->fcode,
384                                                    pParam, pMBs, prevMBs, &pMB->mvs[3], &pMB->pmvs[3]);
385    
386                          /* decide: MODE_INTER or MODE_INTER4V                          /* decide: MODE_INTER or MODE_INTER4V
387                             mpeg4:   if (sad8 < sad16 - nb/2+1) use_inter4v                             mpeg4:   if (sad8 < pMB->sad16 - nb/2+1) use_inter4v
388                          */                          */
389    
390                          if (pMB->dquant == NO_CHANGE) {                                  if (sad8 < pMB->sad16)
391                                  if (((pParam->global_flags & XVID_INTER4V)==0) ||                                  {
                                     (sad16 < (sad8 + (int32_t)(IMV16X16 * pParam->quant)))) {  
   
                                         sad8 = sad16;  
                                         pMB->mode = MODE_INTER;  
                                         pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = mv16.x;  
                                         pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = mv16.y;  
                                         pMB->pmvs[0].x = pmv16.x;  
                                         pMB->pmvs[0].y = pmv16.y;  
                                 }  
                                 else  
392                                          pMB->mode = MODE_INTER4V;                                          pMB->mode = MODE_INTER4V;
393                   pMB->sad8[0] *= 4;
394                                            pMB->sad8[1] *= 4;
395                                            pMB->sad8[2] *= 4;
396                                            pMB->sad8[3] *= 4;
397                                            continue;
398                          }                          }
                         else  
                         {  
                                 sad8 = sad16;  
                                 pMB->mode = MODE_INTER;  
                                 pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = mv16.x;  
                                 pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = mv16.y;  
                                 pMB->pmvs[0].x = pmv16.x;  
                                 pMB->pmvs[0].y = pmv16.y;  
399                          }                          }
400                  }                  }
401    
402          return 0;                          pMB->mode = MODE_INTER;
403  }                          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mv16;
404             pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = pMB->sad16;
405    
406  #define MVzero(A) ( ((A).x)==(0) && ((A).y)==(0) )                          pmv = get_pmv(pMBs, x, y, pParam->mb_width, 0);
407                            // get_pmv has to be called again.
408                            // intra-decision and inter4v change predictors
409    
410  #define MVequal(A,B) ( ((A).x)==((B).x) && ((A).y)==((B).y) )                                  pMB->pmvs[0].x = pMB->mv16.x - pmv.x;
411                                    pMB->pmvs[0].y = pMB->mv16.y - pmv.y;
412                    }
413    
414            return 0;
415    }
416    
417  #define CHECK_MV16_ZERO {\  #define CHECK_MV16_ZERO {\
418    if ( (0 <= max_dx) && (0 >= min_dx) \    if ( (0 <= max_dx) && (0 >= min_dx) \
419      && (0 <= max_dy) && (0 >= min_dy) ) \      && (0 <= max_dy) && (0 >= min_dy) ) \
420    { \    { \
421      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0, 0 , iEdgedWidth), iEdgedWidth, MV_MAX_ERROR); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0, 0 , iEdgedWidth), iEdgedWidth, MV_MAX_ERROR); \
422      iSAD += calc_delta_16(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode, iQuant);\
     if (iSAD <= iQuant * 96)    \  
         iSAD -= MV16_00_BIAS; \  
423      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
424      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \
425  }  }
426    
427  #define NOCHECK_MV16_CANDIDATE(X,Y) { \  #define NOCHECK_MV16_CANDIDATE(X,Y) { \
428      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
429      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\
430      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
431      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
432  }  }
# Line 457  Line 436 
436      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
437    { \    { \
438      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
439      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\
440      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
441      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
442  }  }
# Line 467  Line 446 
446      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
447    { \    { \
448      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
449      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\
450      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
451      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
452  }  }
# Line 477  Line 456 
456      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
457    { \    { \
458      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
459      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\
460      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
461      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
462  }  }
# Line 485  Line 464 
464    
465  #define CHECK_MV8_ZERO {\  #define CHECK_MV8_ZERO {\
466    iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, 0, 0 , iEdgedWidth), iEdgedWidth); \    iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, 0, 0 , iEdgedWidth), iEdgedWidth); \
467    iSAD += calc_delta_8(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode) * iQuant;\    iSAD += calc_delta_8(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode, iQuant);\
468    if (iSAD < iMinSAD) \    if (iSAD < iMinSAD) \
469    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \
470  }  }
# Line 493  Line 472 
472  #define NOCHECK_MV8_CANDIDATE(X,Y) \  #define NOCHECK_MV8_CANDIDATE(X,Y) \
473    { \    { \
474      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
475      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\
476      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
477      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
478  }  }
# Line 503  Line 482 
482      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
483    { \    { \
484      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
485      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\
486      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
487      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
488  }  }
# Line 513  Line 492 
492      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
493    { \    { \
494      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
495      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\
496      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
497      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
498  }  }
# Line 523  Line 502 
502      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
503    { \    { \
504      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
505      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\
506      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
507      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
508  }  }
# Line 538  Line 517 
517                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
518                                          const int x, const int y,                                          const int x, const int y,
519                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
520                                            const uint32_t iQuant,
521                                            const uint32_t iFcode,
522                                          MBParam * const pParam,                                          MBParam * const pParam,
523                                          MACROBLOCK * const pMBs,                                          const MACROBLOCK * const pMBs,
524                                            const MACROBLOCK * const prevMBs,
525                                          VECTOR * const currMV,                                          VECTOR * const currMV,
526                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
527  {  {
528          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
         const int32_t iQuant = pParam->quant;  
529          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
530          int32_t iSAD;          int32_t iSAD;
531          int32_t pred_x,pred_y;          int32_t pred_x,pred_y;
# Line 866  Line 847 
847                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
848                                          const int x, const int y,                                          const int x, const int y,
849                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
850                                            const uint32_t iQuant,
851                                            const uint32_t iFcode,
852                                          const MBParam * const pParam,                                          const MBParam * const pParam,
853                                          MACROBLOCK * const pMBs,                                          const MACROBLOCK * const pMBs,
854                                            const MACROBLOCK * const prevMBs,
855                                          VECTOR * const currMV,                                          VECTOR * const currMV,
856                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
857  {  {
858          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;  
859          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
860          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
861          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
# Line 895  Line 877 
877          VECTOR pmv[4];          VECTOR pmv[4];
878          int32_t psad[4];          int32_t psad[4];
879    
880          MACROBLOCK * const pMB = pMBs + x + y * iWcount;  //      const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
881            const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
882    
883          static int32_t threshA,threshB;          static int32_t threshA,threshB;
884          int32_t bPredEq;          int32_t bPredEq;
# Line 934  Line 917 
917    
918          iFound=0;          iFound=0;
919    
 /* Step 2: Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion  
    vector of the median.  
    If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2  
 */  
   
         if ((bPredEq) && (MVequal(pmv[0],pMB->mvs[0]) ) )  
                 iFound=2;  
   
 /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.  
    Otherwise select large Diamond Search.  
 */  
   
         if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536) || (bPredEq) )  
                 iDiamondSize=1; // halfpel!  
         else  
                 iDiamondSize=2; // halfpel!  
   
         if (!(MotionFlags & PMV_HALFPELDIAMOND16) )  
                 iDiamondSize*=2;  
   
920  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
921     MinSAD=SAD     MinSAD=SAD
922     If Motion Vector equal to Previous frame motion vector     If Motion Vector equal to Previous frame motion vector
# Line 961  Line 924 
924     If SAD<=256 goto Step 10.     If SAD<=256 goto Step 10.
925  */  */
926    
   
 // Prepare for main loop  
   
927          *currMV=pmv[0];         /* current best := prediction */          *currMV=pmv[0];         /* current best := prediction */
928          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16 ))
929          {       /* This should NOT be necessary! */          {       /* This should NOT be necessary! */
# Line 991  Line 951 
951          iMinSAD = sad16( cur,          iMinSAD = sad16( cur,
952                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),
953                           iEdgedWidth, MV_MAX_ERROR);                           iEdgedWidth, MV_MAX_ERROR);
954          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);
955    
956          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && (iMinSAD < pMB->sad16) ) )          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )
957            {
958                    if (iMinSAD < 2*iQuant) // high chances for SKIP-mode
959                    {
960                            if (!MVzero(*currMV))
961          {          {
962                                    iMinSAD += MV16_00_BIAS;
963                                    CHECK_MV16_ZERO;                // (0,0) saves space for letterboxed pictures
964                                    iMinSAD -= MV16_00_BIAS;
965                            }
966                    }
967    
968                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
969                          goto PMVfast16_Terminate_without_Refine;                          goto PMVfast16_Terminate_without_Refine;
# Line 1002  Line 971 
971                          goto PMVfast16_Terminate_with_Refine;                          goto PMVfast16_Terminate_with_Refine;
972          }          }
973    
974    
975    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
976       vector of the median.
977       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
978    */
979    
980            if ((bPredEq) && (MVequal(pmv[0],prevMB->mvs[0]) ) )
981                    iFound=2;
982    
983    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
984       Otherwise select large Diamond Search.
985    */
986    
987            if ( (!MVzero(pmv[0])) || (threshB<1536) || (bPredEq) )
988                    iDiamondSize=1; // halfpel!
989            else
990                    iDiamondSize=2; // halfpel!
991    
992            if (!(MotionFlags & PMV_HALFPELDIAMOND16) )
993                    iDiamondSize*=2;
994    
995  /*  /*
996     Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.     Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.
997     Also calculate (0,0) but do not subtract offset.     Also calculate (0,0) but do not subtract offset.
998     Let MinSAD be the smallest SAD up to this point.     Let MinSAD be the smallest SAD up to this point.
999     If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
1000  */  */
1001    
1002  // (0,0) is always possible  // (0,0) is always possible
1003    
1004            if (!MVzero(pmv[0]))
1005          CHECK_MV16_ZERO;          CHECK_MV16_ZERO;
1006    
1007  // previous frame MV is always possible  // previous frame MV is always possible
1008          CHECK_MV16_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);  
1009            if (!MVzero(prevMB->mvs[0]))
1010            if (!MVequal(prevMB->mvs[0],pmv[0]))
1011                    CHECK_MV16_CANDIDATE(prevMB->mvs[0].x,prevMB->mvs[0].y);
1012    
1013  // left neighbour, if allowed  // left neighbour, if allowed
1014          if (x != 0)  
1015            if (!MVzero(pmv[1]))
1016            if (!MVequal(pmv[1],prevMB->mvs[0]))
1017            if (!MVequal(pmv[1],pmv[0]))
1018          {          {
1019                  if (!(MotionFlags & PMV_HALFPEL16 ))                  if (!(MotionFlags & PMV_HALFPEL16 ))
1020                  {       pmv[1].x = EVEN(pmv[1].x);                  {       pmv[1].x = EVEN(pmv[1].x);
1021                  pmv[1].y = EVEN(pmv[1].y);                  pmv[1].y = EVEN(pmv[1].y);
1022                  }                  }
1023    
1024                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1025          }          }
1026    
1027  // top neighbour, if allowed  // top neighbour, if allowed
1028          if (y != 0)          if (!MVzero(pmv[2]))
1029            if (!MVequal(pmv[2],prevMB->mvs[0]))
1030            if (!MVequal(pmv[2],pmv[0]))
1031            if (!MVequal(pmv[2],pmv[1]))
1032          {          {
1033                  if (!(MotionFlags & PMV_HALFPEL16 ))                  if (!(MotionFlags & PMV_HALFPEL16 ))
1034                  {       pmv[2].x = EVEN(pmv[2].x);                  {       pmv[2].x = EVEN(pmv[2].x);
# Line 1036  Line 1037 
1037                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1038    
1039  // top right neighbour, if allowed  // top right neighbour, if allowed
1040                  if (x != (iWcount-1))                  if (!MVzero(pmv[3]))
1041                    if (!MVequal(pmv[3],prevMB->mvs[0]))
1042                    if (!MVequal(pmv[3],pmv[0]))
1043                    if (!MVequal(pmv[3],pmv[1]))
1044                    if (!MVequal(pmv[3],pmv[2]))
1045                  {                  {
1046                          if (!(MotionFlags & PMV_HALFPEL16 ))                          if (!(MotionFlags & PMV_HALFPEL16 ))
1047                          {       pmv[3].x = EVEN(pmv[3].x);                          {       pmv[3].x = EVEN(pmv[3].x);
# Line 1046  Line 1051 
1051                  }                  }
1052          }          }
1053    
1054            if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96)*/ )
1055                    iMinSAD -= MV16_00_BIAS;
1056    
1057    
1058  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
1059     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
1060  */  */
1061    
1062          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[0]) && (iMinSAD < pMB->sad16) ) )          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[0]) && ((uint32_t)iMinSAD < prevMB->sad16) ) )
1063          {          {
1064                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1065                          goto PMVfast16_Terminate_without_Refine;                          goto PMVfast16_Terminate_without_Refine;
# Line 1236  Line 1245 
1245                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1246                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1247                                          const int x, const int y,                                          const int x, const int y,
1248                                          const int start_x, int start_y,                                          const int start_x, const int start_y,
1249                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1250                                            const uint32_t iQuant,
1251                                            const uint32_t iFcode,
1252                                          const MBParam * const pParam,                                          const MBParam * const pParam,
1253                                          MACROBLOCK * const pMBs,                                          const MACROBLOCK * const pMBs,
1254                                            const MACROBLOCK * const prevMBs,
1255                                          VECTOR * const currMV,                                          VECTOR * const currMV,
1256                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
1257  {  {
1258          const uint32_t iWcount = pParam->mb_width;          const uint32_t iWcount = pParam->mb_width;
   
         const int32_t iFcode = pParam->fixed_code;  
         const int32_t iQuant = pParam->quant;  
1259          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
1260          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
1261          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
# Line 1264  Line 1273 
1273          int32_t psad[4];          int32_t psad[4];
1274          VECTOR newMV;          VECTOR newMV;
1275          VECTOR backupMV;          VECTOR backupMV;
1276            VECTOR startMV;
1277    
1278          MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;  //      const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1279            const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;
1280    
1281          static int32_t threshA,threshB;          static int32_t threshA,threshB;
1282          int32_t iFound,bPredEq;          int32_t iFound,bPredEq;
1283          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
1284    
1285          int32_t iSubBlock = ((y&1)<<1) + (x&1);          int32_t iSubBlock = (y&1)+(y&1) + (x&1);
1286    
1287            /* Init variables */
1288            startMV.x = start_x;
1289            startMV.y = start_y;
1290    
1291  /* Get maximum range */  /* Get maximum range */
1292          get_range(&min_dx, &max_dx, &min_dy, &max_dy,          get_range(&min_dx, &max_dx, &min_dy, &max_dy,
1293                    x, y, 8, iWidth, iHeight, iFcode);                    x, y, 8, iWidth, iHeight, iFcode);
1294    
 /* we work with abs. MVs, not relative to prediction, so range is relative to 0,0 */  
   
1295          if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))          if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))
1296          { min_dx = EVEN(min_dx);          { min_dx = EVEN(min_dx);
1297          max_dx = EVEN(max_dx);          max_dx = EVEN(max_dx);
# Line 1306  Line 1319 
1319    
1320          iFound=0;          iFound=0;
1321    
 /* Step 2: Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion  
    vector of the median.  
    If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2  
 */  
   
         if ((bPredEq) && (MVequal(pmv[0],pMB->mvs[iSubBlock]) ) )  
                 iFound=2;  
   
 /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.  
    Otherwise select large Diamond Search.  
 */  
   
         if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536/4) || (bPredEq) )  
                 iDiamondSize=1; // 1 halfpel!  
         else  
                 iDiamondSize=2; // 2 halfpel = 1 full pixel!  
   
         if (!(MotionFlags & PMV_HALFPELDIAMOND8) )  
                 iDiamondSize*=2;  
   
1322  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
1323     MinSAD=SAD     MinSAD=SAD
1324     If Motion Vector equal to Previous frame motion vector     If Motion Vector equal to Previous frame motion vector
# Line 1336  Line 1329 
1329    
1330  // Prepare for main loop  // Prepare for main loop
1331    
1332          currMV->x=start_x;              /* start with mv16 */          *currMV = startMV;
         currMV->y=start_y;  
1333    
1334          iMinSAD = sad8( cur,          iMinSAD = sad8( cur,
1335                          get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),                          get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),
1336                          iEdgedWidth);                          iEdgedWidth);
1337          iMinSAD += calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y, (uint8_t)iFcode) * iQuant;          iMinSAD += calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y, (uint8_t)iFcode, iQuant);
1338    
1339          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,pMB->mvs[iSubBlock])) && (iMinSAD < pMB->sad8[iSubBlock]) ) )          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,prevMB->mvs[iSubBlock]))
1340                                    && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )
1341          {          {
1342                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1343                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
# Line 1352  Line 1345 
1345                          goto PMVfast8_Terminate_with_Refine;                          goto PMVfast8_Terminate_with_Refine;
1346          }          }
1347    
1348    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
1349       vector of the median.
1350       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1351    */
1352    
1353            if ((bPredEq) && (MVequal(pmv[0],prevMB->mvs[iSubBlock]) ) )
1354                    iFound=2;
1355    
1356    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
1357       Otherwise select large Diamond Search.
1358    */
1359    
1360            if ( (!MVzero(pmv[0])) || (threshB<1536/4) || (bPredEq) )
1361                    iDiamondSize=1; // 1 halfpel!
1362            else
1363                    iDiamondSize=2; // 2 halfpel = 1 full pixel!
1364    
1365            if (!(MotionFlags & PMV_HALFPELDIAMOND8) )
1366                    iDiamondSize*=2;
1367    
1368    
1369  /*  /*
1370     Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.     Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.
1371     Also calculate (0,0) but do not subtract offset.     Also calculate (0,0) but do not subtract offset.
1372     Let MinSAD be the smallest SAD up to this point.     Let MinSAD be the smallest SAD up to this point.
1373     If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
1374  */  */
1375    
1376  // the prediction might be even better than mv16  // the median prediction might be even better than mv16
1377    
1378            if (!MVequal(pmv[0],startMV))
1379          CHECK_MV8_CANDIDATE(pmv[0].x,pmv[0].y);          CHECK_MV8_CANDIDATE(pmv[0].x,pmv[0].y);
1380    
1381  // (0,0) is always possible  // (0,0) if needed
1382            if (!MVzero(pmv[0]))
1383            if (!MVzero(startMV))
1384          CHECK_MV8_ZERO;          CHECK_MV8_ZERO;
1385    
1386  // previous frame MV is always possible  // previous frame MV if needed
1387          CHECK_MV8_CANDIDATE(pMB->mvs[iSubBlock].x,pMB->mvs[iSubBlock].y);          if (!MVzero(prevMB->mvs[iSubBlock]))
1388            if (!MVequal(prevMB->mvs[iSubBlock],startMV))
1389            if (!MVequal(prevMB->mvs[iSubBlock],pmv[0]))
1390            CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);
1391    
1392  // left neighbour, if allowed          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[iSubBlock]) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )
1393          if (psad[1] != MV_MAX_ERROR)          {
1394                    if (MotionFlags & PMV_QUICKSTOP16)
1395                            goto PMVfast8_Terminate_without_Refine;
1396                    if (MotionFlags & PMV_EARLYSTOP16)
1397                            goto PMVfast8_Terminate_with_Refine;
1398            }
1399    
1400    
1401    // left neighbour, if allowed and needed
1402            if (!MVzero(pmv[1]))
1403            if (!MVequal(pmv[1],startMV))
1404            if (!MVequal(pmv[1],prevMB->mvs[iSubBlock]))
1405            if (!MVequal(pmv[1],pmv[0]))
1406          {          {
1407                  if (!(MotionFlags & PMV_HALFPEL8 ))                  if (!(MotionFlags & PMV_HALFPEL8 ))
1408                  {       pmv[1].x = EVEN(pmv[1].x);                  {       pmv[1].x = EVEN(pmv[1].x);
# Line 1379  Line 1411 
1411                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
1412          }          }
1413    
1414  // top neighbour, if allowed  // top neighbour, if allowed and needed
1415          if (psad[2] != MV_MAX_ERROR)          if (!MVzero(pmv[2]))
1416            if (!MVequal(pmv[2],startMV))
1417            if (!MVequal(pmv[2],prevMB->mvs[iSubBlock]))
1418            if (!MVequal(pmv[2],pmv[0]))
1419            if (!MVequal(pmv[2],pmv[1]))
1420          {          {
1421                  if (!(MotionFlags & PMV_HALFPEL8 ))                  if (!(MotionFlags & PMV_HALFPEL8 ))
1422                  {       pmv[2].x = EVEN(pmv[2].x);                  {       pmv[2].x = EVEN(pmv[2].x);
# Line 1388  Line 1424 
1424                  }                  }
1425                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
1426    
1427  // top right neighbour, if allowed  // top right neighbour, if allowed and needed
1428                  if (psad[3] != MV_MAX_ERROR)          if (!MVzero(pmv[3]))
1429            if (!MVequal(pmv[3],startMV))
1430            if (!MVequal(pmv[3],prevMB->mvs[iSubBlock]))
1431            if (!MVequal(pmv[3],pmv[0]))
1432            if (!MVequal(pmv[3],pmv[1]))
1433            if (!MVequal(pmv[3],pmv[2]))
1434                  {                  {
1435                          if (!(MotionFlags & PMV_HALFPEL8 ))                          if (!(MotionFlags & PMV_HALFPEL8 ))
1436                          {       pmv[3].x = EVEN(pmv[3].x);                          {       pmv[3].x = EVEN(pmv[3].x);
# Line 1399  Line 1440 
1440                  }                  }
1441          }          }
1442    
1443            if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1444                    iMinSAD -= MV8_00_BIAS;
1445    
1446    
1447  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
1448     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
1449  */  */
1450    
1451          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[iSubBlock]) && (iMinSAD < pMB->sad8[iSubBlock]) ) )          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[iSubBlock]) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )
1452          {          {
1453                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1454                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
# Line 1493  Line 1538 
1538                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1539                                          const int x, const int y,                                          const int x, const int y,
1540                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1541                                            const uint32_t iQuant,
1542                                            const uint32_t iFcode,
1543                                          const MBParam * const pParam,                                          const MBParam * const pParam,
1544                                          MACROBLOCK * const pMBs,                                          const MACROBLOCK * const pMBs,
1545                                            const MACROBLOCK * const prevMBs,
1546                                          VECTOR * const currMV,                                          VECTOR * const currMV,
1547                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
1548  {  {
1549          const uint32_t iWcount = pParam->mb_width;          const uint32_t iWcount = pParam->mb_width;
1550          const uint32_t iHcount = pParam->mb_height;          const uint32_t iHcount = pParam->mb_height;
         const int32_t iFcode = pParam->fixed_code;  
         const int32_t iQuant = pParam->quant;  
1551    
1552          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
1553          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
# Line 1521  Line 1567 
1567          int32_t psad[8];          int32_t psad[8];
1568    
1569          static MACROBLOCK * oldMBs = NULL;          static MACROBLOCK * oldMBs = NULL;
1570          MACROBLOCK * const pMB = pMBs + x + y * iWcount;  //      const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
1571            const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
1572          MACROBLOCK * oldMB = NULL;          MACROBLOCK * oldMB = NULL;
1573    
1574          static int32_t thresh2;          static int32_t thresh2;
# Line 1531  Line 1578 
1578          MainSearch16FuncPtr EPZSMainSearchPtr;          MainSearch16FuncPtr EPZSMainSearchPtr;
1579    
1580          if (oldMBs == NULL)          if (oldMBs == NULL)
1581          {       oldMBs = (MACROBLOCK*) calloc(1,iWcount*iHcount*sizeof(MACROBLOCK));          {       oldMBs = (MACROBLOCK*) calloc(iWcount*iHcount,sizeof(MACROBLOCK));
1582                  fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));  //              fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));
1583          }          }
1584          oldMB = oldMBs + x + y * iWcount;          oldMB = oldMBs + x + y * iWcount;
1585    
# Line 1540  Line 1587 
1587          get_range(&min_dx, &max_dx, &min_dy, &max_dy,          get_range(&min_dx, &max_dx, &min_dy, &max_dy,
1588                          x, y, 16, iWidth, iHeight, iFcode);                          x, y, 16, iWidth, iHeight, iFcode);
1589    
 /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */  
   
1590          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16 ))
1591          { min_dx = EVEN(min_dx);          { min_dx = EVEN(min_dx);
1592            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
# Line 1581  Line 1626 
1626          iMinSAD = sad16( cur,          iMinSAD = sad16( cur,
1627                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),
1628                  iEdgedWidth, MV_MAX_ERROR);                  iEdgedWidth, MV_MAX_ERROR);
1629          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);
1630    
1631  // thresh1 is fixed to 256  // thresh1 is fixed to 256
1632          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && (iMinSAD < pMB->sad16) ) )          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV, prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )
1633                  {                  {
1634                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
1635                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
# Line 1595  Line 1640 
1640  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
1641    
1642  // previous frame MV  // previous frame MV
1643          CHECK_MV16_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);          CHECK_MV16_CANDIDATE(prevMB->mvs[0].x,prevMB->mvs[0].y);
1644    
1645  // set threshhold based on Min of Prediction and SAD of collocated block  // set threshhold based on Min of Prediction and SAD of collocated block
1646  // CHECK_MV16 always uses iSAD for the SAD of last vector to check, so now iSAD is what we want  // CHECK_MV16 always uses iSAD for the SAD of last vector to check, so now iSAD is what we want
# Line 1636  Line 1681 
1681                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1682    
1683  // top right neighbour, if allowed  // top right neighbour, if allowed
1684                  if (x != (iWcount-1))                  if ((uint32_t)x != (iWcount-1))
1685                  {                  {
1686                          if (!(MotionFlags & PMV_HALFPEL16 ))                          if (!(MotionFlags & PMV_HALFPEL16 ))
1687                          {       pmv[3].x = EVEN(pmv[3].x);                          {       pmv[3].x = EVEN(pmv[3].x);
# Line 1651  Line 1696 
1696  */  */
1697    
1698          if ( (iMinSAD <= thresh2)          if ( (iMinSAD <= thresh2)
1699                  || ( MVequal(*currMV,pMB->mvs[0]) && (iMinSAD <= pMB->sad16) ) )                  || ( MVequal(*currMV,prevMB->mvs[0]) && ((uint32_t)iMinSAD <= prevMB->sad16) ) )
1700                  {                  {
1701                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
1702                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
# Line 1661  Line 1706 
1706    
1707  /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/  /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/
1708    
1709          backupMV = pMB->mvs[0];                 // last MV          backupMV = prevMB->mvs[0];              // collocated MV
1710          backupMV.x += (pMB->mvs[0].x - oldMB->mvs[0].x );       // acceleration X          backupMV.x += (prevMB->mvs[0].x - oldMB->mvs[0].x );    // acceleration X
1711          backupMV.y += (pMB->mvs[0].y - oldMB->mvs[0].y );       // acceleration Y          backupMV.y += (prevMB->mvs[0].y - oldMB->mvs[0].y );    // acceleration Y
1712    
1713          CHECK_MV16_CANDIDATE(backupMV.x,backupMV.y);          CHECK_MV16_CANDIDATE(backupMV.x,backupMV.y);
1714    
1715  // left neighbour  // left neighbour
1716          if (x != 0)          if (x != 0)
1717                  CHECK_MV16_CANDIDATE((oldMB-1)->mvs[0].x,oldMB->mvs[0].y);                  CHECK_MV16_CANDIDATE((prevMB-1)->mvs[0].x,(prevMB-1)->mvs[0].y);
1718    
1719  // top neighbour  // top neighbour
1720          if (y != 0)          if (y != 0)
1721                  CHECK_MV16_CANDIDATE((oldMB-iWcount)->mvs[0].x,oldMB->mvs[0].y);                  CHECK_MV16_CANDIDATE((prevMB-iWcount)->mvs[0].x,(prevMB-iWcount)->mvs[0].y);
1722    
1723  // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs  // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs
1724    
1725          if (x != iWcount-1)          if ((uint32_t)x != iWcount-1)
1726                  CHECK_MV16_CANDIDATE((pMB+1)->mvs[0].x,oldMB->mvs[0].y);                  CHECK_MV16_CANDIDATE((prevMB+1)->mvs[0].x,(prevMB+1)->mvs[0].y);
1727    
1728  // bottom neighbour, dito  // bottom neighbour, dito
1729          if (y != iHcount-1)          if ((uint32_t)y != iHcount-1)
1730                  CHECK_MV16_CANDIDATE((pMB+iWcount)->mvs[0].x,oldMB->mvs[0].y);                  CHECK_MV16_CANDIDATE((prevMB+iWcount)->mvs[0].x,(prevMB+iWcount)->mvs[0].y);
1731    
1732  /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */  /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */
1733          if (iMinSAD <= thresh2)          if (iMinSAD <= thresh2)
# Line 1739  Line 1784 
1784                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1785                                  x, y,                                  x, y,
1786                          0, 0, iMinSAD, &newMV,                          0, 0, iMinSAD, &newMV,
1787                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, /*iDiamondSize*/ 2, iFcode, iQuant, 0);                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
1788    
1789                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD)
1790                          {                          {
# Line 1760  Line 1805 
1805    
1806  EPZS16_Terminate_without_Refine:  EPZS16_Terminate_without_Refine:
1807    
1808          *oldMB = *pMB;          *oldMB = *prevMB;
1809    
1810          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - pmv[0].x;
1811          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - pmv[0].y;
# Line 1777  Line 1822 
1822                                          const int x, const int y,                                          const int x, const int y,
1823                                          const int start_x, const int start_y,                                          const int start_x, const int start_y,
1824                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1825                                            const uint32_t iQuant,
1826                                            const uint32_t iFcode,
1827                                          const MBParam * const pParam,                                          const MBParam * const pParam,
1828                                          MACROBLOCK * const pMBs,                                          const MACROBLOCK * const pMBs,
1829                                            const MACROBLOCK * const prevMBs,
1830                                          VECTOR * const currMV,                                          VECTOR * const currMV,
1831                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
1832  {  {
1833          const uint32_t iWcount = pParam->mb_width;  /* Please not that EPZS might not be a good choice for 8x8-block motion search ! */
         const int32_t iFcode = pParam->fixed_code;  
         const int32_t iQuant = pParam->quant;  
1834    
1835            const uint32_t iWcount = pParam->mb_width;
1836          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
1837          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
1838          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
# Line 1807  Line 1854 
1854    
1855          const   int32_t iSubBlock = ((y&1)<<1) + (x&1);          const   int32_t iSubBlock = ((y&1)<<1) + (x&1);
1856    
1857          MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;  //      const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1858            const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;
1859    
1860          int32_t bPredEq;          int32_t bPredEq;
1861          int32_t iMinSAD,iSAD=9999;          int32_t iMinSAD,iSAD=9999;
# Line 1861  Line 1909 
1909          iMinSAD = sad8( cur,          iMinSAD = sad8( cur,
1910                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),
1911                  iEdgedWidth);                  iEdgedWidth);
1912          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);
1913    
1914    
1915  // thresh1 is fixed to 256  // thresh1 is fixed to 256
# Line 1875  Line 1923 
1923    
1924  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
1925    
 // previous frame MV  
         CHECK_MV8_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);  
1926    
1927  // MV=(0,0) is often a good choice  // MV=(0,0) is often a good choice
   
1928          CHECK_MV8_ZERO;          CHECK_MV8_ZERO;
1929    
1930    // previous frame MV
1931            CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);
1932    
1933    // left neighbour, if allowed
1934            if (psad[1] != MV_MAX_ERROR)
1935            {
1936                    if (!(MotionFlags & PMV_HALFPEL8 ))
1937                    {       pmv[1].x = EVEN(pmv[1].x);
1938                            pmv[1].y = EVEN(pmv[1].y);
1939                    }
1940                    CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
1941            }
1942    
1943    // top neighbour, if allowed
1944            if (psad[2] != MV_MAX_ERROR)
1945            {
1946                    if (!(MotionFlags & PMV_HALFPEL8 ))
1947                    {       pmv[2].x = EVEN(pmv[2].x);
1948                            pmv[2].y = EVEN(pmv[2].y);
1949                    }
1950                    CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
1951    
1952    // top right neighbour, if allowed
1953                    if (psad[3] != MV_MAX_ERROR)
1954                    {
1955                            if (!(MotionFlags & PMV_HALFPEL8 ))
1956                            {       pmv[3].x = EVEN(pmv[3].x);
1957                                    pmv[3].y = EVEN(pmv[3].y);
1958                            }
1959                            CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);
1960                    }
1961            }
1962    
1963    /*  // this bias is zero anyway, at the moment!
1964    
1965            if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) ) // && (iMinSAD <= iQuant * 96)
1966                    iMinSAD -= MV8_00_BIAS;
1967    
1968    */
1969    
1970  /* Terminate if MinSAD <= T_2  /* Terminate if MinSAD <= T_2
1971     Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]     Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
1972  */  */
# Line 1894  Line 1979 
1979                                  goto EPZS8_Terminate_with_Refine;                                  goto EPZS8_Terminate_with_Refine;
1980                  }                  }
1981    
1982  /************ (if Diamond Search)  **************/  /************ (Diamond Search)  **************/
1983    
1984          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1985    
1986          if (!(MotionFlags & PMV_HALFPELDIAMOND8))          if (!(MotionFlags & PMV_HALFPELDIAMOND8))
1987                  iDiamondSize *= 2;                  iDiamondSize *= 2;
1988    
1989  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */  /* default: use best prediction as starting point for one call of EPZS_MainSearch */
1990    
1991    /* // there is no EPZS^2 for inter4v at the moment
1992    
1993            if (MotionFlags & PMV_USESQUARES8)
1994                    EPZSMainSearchPtr = Square8_MainSearch;
1995            else
1996    */
1997    
 //      if (MotionFlags & PMV_USESQUARES8)  
 //              EPZSMainSearchPtr = Square8_MainSearch;  
 //      else  
1998                  EPZSMainSearchPtr = Diamond8_MainSearch;                  EPZSMainSearchPtr = Diamond8_MainSearch;
1999    
2000          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
2001                  x, y,                  x, y,
2002                  currMV->x, currMV->y, iMinSAD, &newMV,                  currMV->x, currMV->y, iMinSAD, &newMV,
2003                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2004                  iDiamondSize, iFcode, iQuant, 00);                  iDiamondSize, iFcode, iQuant, 0);
2005    
2006    
2007          if (iSAD < iMinSAD)          if (iSAD < iMinSAD)
# Line 1970  Line 2059 
2059          return iMinSAD;          return iMinSAD;
2060  }  }
2061    
2062    
2063    
2064    
2065    
2066    /* ***********************************************************
2067            bvop motion estimation
2068    // TODO: need to incorporate prediction here (eg. sad += calc_delta_16)
2069    ***************************************************************/
2070    
2071    
2072    void MotionEstimationBVOP(
2073                            MBParam * const pParam,
2074                            FRAMEINFO * const frame,
2075    
2076                            // forward (past) reference
2077                            const MACROBLOCK * const f_mbs,
2078                        const IMAGE * const f_ref,
2079                            const IMAGE * const f_refH,
2080                        const IMAGE * const f_refV,
2081                            const IMAGE * const f_refHV,
2082                            // backward (future) reference
2083                            const MACROBLOCK * const b_mbs,
2084                        const IMAGE * const b_ref,
2085                            const IMAGE * const b_refH,
2086                        const IMAGE * const b_refV,
2087                            const IMAGE * const b_refHV)
2088    {
2089        const uint32_t mb_width = pParam->mb_width;
2090        const uint32_t mb_height = pParam->mb_height;
2091            const int32_t edged_width = pParam->edged_width;
2092    
2093            uint32_t i,j;
2094    
2095            int32_t f_sad16;
2096            int32_t b_sad16;
2097            int32_t i_sad16;
2098            int32_t d_sad16;
2099            int32_t best_sad;
2100    
2101            VECTOR pmv_dontcare;
2102    
2103            // note: i==horizontal, j==vertical
2104        for (j = 0; j < mb_height; j++)
2105            {
2106                    for (i = 0; i < mb_width; i++)
2107                    {
2108                            MACROBLOCK *mb = &frame->mbs[i + j*mb_width];
2109                            const MACROBLOCK *f_mb = &f_mbs[i + j*mb_width];
2110                            const MACROBLOCK *b_mb = &b_mbs[i + j*mb_width];
2111    
2112                            if (b_mb->mode == MODE_INTER
2113                                    && b_mb->cbp == 0
2114                                    && b_mb->mvs[0].x == 0
2115                                    && b_mb->mvs[0].y == 0)
2116                            {
2117                                    mb->mode = MODE_NOT_CODED;
2118                                    mb->mvs[0].x = 0;
2119                                    mb->mvs[0].y = 0;
2120                                    mb->b_mvs[0].x = 0;
2121                                    mb->b_mvs[0].y = 0;
2122                                    continue;
2123                            }
2124    
2125    
2126                            // forward search
2127                            f_sad16 = SEARCH16(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2128                                                    &frame->image,
2129                                                    i, j,
2130                                                    frame->motion_flags,  frame->quant, frame->fcode,
2131                                                    pParam,
2132                                                    f_mbs, f_mbs /* todo */,
2133                                                    &mb->mvs[0], &pmv_dontcare);    // ignore pmv
2134    
2135                            // backward search
2136                            b_sad16 = SEARCH16(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
2137                                                    &frame->image,
2138                                                    i, j,
2139                                                    frame->motion_flags,  frame->quant, frame->bcode,
2140                                                    pParam,
2141                                                    b_mbs, b_mbs, /* todo */
2142                                                    &mb->b_mvs[0], &pmv_dontcare);  // ignore pmv
2143    
2144                            // interpolate search (simple, but effective)
2145                            i_sad16 = sad16bi_c(
2146                                            frame->image.y + i*16 + j*16*edged_width,
2147                                            get_ref(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2148                                                    i, j, 16, mb->mvs[0].x, mb->mvs[0].y, edged_width),
2149                                            get_ref(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
2150                                                    i, j, 16, mb->b_mvs[0].x, mb->b_mvs[0].x, edged_width),
2151                                            edged_width);
2152    
2153                            // TODO: direct search
2154                            // predictor + range of [-32,32]
2155                            d_sad16 = 65535;
2156    
2157    
2158                            if (f_sad16 < b_sad16)
2159                            {
2160                                    best_sad = f_sad16;
2161                                    mb->mode = MODE_FORWARD;
2162                            }
2163                            else
2164                            {
2165                                    best_sad = b_sad16;
2166                                    mb->mode = MODE_BACKWARD;
2167                            }
2168    
2169                            if (i_sad16 < best_sad)
2170                            {
2171                                    best_sad = i_sad16;
2172                                    mb->mode = MODE_INTERPOLATE;
2173                            }
2174    
2175                            if (d_sad16 < best_sad)
2176                            {
2177                                    best_sad = d_sad16;
2178                                    mb->mode = MODE_DIRECT;
2179                            }
2180    
2181                    }
2182            }
2183    }

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

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