[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 136, Thu Apr 25 06:55:00 2002 UTC revision 184, Mon May 27 18:07:38 2002 UTC
# Line 2  Line 2 
2   *   *
3   *  Modifications:   *  Modifications:
4   *   *
5     *      01.05.2002      updated MotionEstimationBVOP
6   *      25.04.2002 partial prevMB conversion   *      25.04.2002 partial prevMB conversion
7   *  22.04.2002 remove some compile warning by chenm001 <chenm001@163.com>   *  22.04.2002 remove some compile warning by chenm001 <chenm001@163.com>
8   *  14.04.2002 added MotionEstimationBVOP()   *  14.04.2002 added MotionEstimationBVOP()
# Line 53  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 67  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(  int32_t PMVfastSearch16(
83                                          const uint8_t * const pRef,                                          const uint8_t * const pRef,
# Line 183  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 218  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)
242  {  {
243          return NEIGH_TEND_16X16 * (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)  static __inline uint32_t calc_delta_8(const int32_t dx, const int32_t dy, const uint32_t iFcode, const uint32_t iQuant)
247    
248  {  {
249      return NEIGH_TEND_8X8 * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));      return NEIGH_TEND_8X8 * lambda_vec8[iQuant] * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));
250  }  }
251    
252    
# Line 252  Line 272 
272          const IMAGE * const pRefV,          const IMAGE * const pRefV,
273          const IMAGE * const pRefHV,          const IMAGE * const pRefHV,
274          const uint32_t iLimit)          const uint32_t iLimit)
   
275  {  {
276          const uint32_t iWcount = pParam->mb_width;          const uint32_t iWcount = pParam->mb_width;
277          const uint32_t iHcount = pParam->mb_height;          const uint32_t iHcount = pParam->mb_height;
278          MACROBLOCK * pMBs = current->mbs;          MACROBLOCK * const pMBs = current->mbs;
279          IMAGE * pCurrent = &current->image;          MACROBLOCK * const prevMBs = reference->mbs;
280            const IMAGE * const pCurrent = &current->image;
281          MACROBLOCK * prevMBs = reference->mbs;  // previous frame          const IMAGE * const pRef = &reference->image;
282          IMAGE * pRef = &reference->image;  
283            const VECTOR zeroMV = {0,0};
284    
285          uint32_t i, j, iIntra = 0;          int32_t x, y;
286            int32_t iIntra = 0;
287          VECTOR mv16;          VECTOR pmv;
         VECTOR pmv16;  
   
         int32_t sad8 = 0;  
         int32_t sad16;  
         int32_t deviation;  
288    
289          if (sadInit)          if (sadInit)
290                  (*sadInit)();                  (*sadInit)();
291    
292            for (y = 0; y < iHcount; y++)
293          /* eventhough we have a seperate prevMBs,                  for (x = 0; x < iWcount; x++)
            pmvfast/epsz does something "funny" with the previous frames data */  
   
         for (i = 0; i < iHcount; i++)  
                 for (j = 0; j < iWcount; j++)  
294                  {                  {
295                          pMBs[j + i * iWcount].mvs[0] = prevMBs[j + i * iWcount].mvs[0];                          MACROBLOCK* const pMB = &pMBs[x + y * iWcount];
                         pMBs[j + i * iWcount].mvs[1] = prevMBs[j + i * iWcount].mvs[1];  
                         pMBs[j + i * iWcount].mvs[2] = prevMBs[j + i * iWcount].mvs[2];  
                         pMBs[j + i * iWcount].mvs[3] = prevMBs[j + i * iWcount].mvs[3];  
                 }  
   
         /*dprintf("*** BEFORE ***");  
         for (i = 0; i < iHcount; i++)  
                 for (j = 0; j < iWcount; j++)  
                 {  
                         dprintf("   [%i,%i] mode=%i dquant=%i mvs=(%i %i %i %i) sad8=(%i %i %i %i) sad16=(%i)", j,i,  
                                 pMBs[j + i * iWcount].mode,  
                                 pMBs[j + i * iWcount].dquant,  
                                 pMBs[j + i * iWcount].mvs[0],  
                                 pMBs[j + i * iWcount].mvs[1],  
                                 pMBs[j + i * iWcount].mvs[2],  
                                 pMBs[j + i * iWcount].mvs[3],  
                                 prevMBs[j + i * iWcount].sad8[0],  
                                 prevMBs[j + i * iWcount].sad8[1],  
                                 prevMBs[j + i * iWcount].sad8[2],  
                                 prevMBs[j + i * iWcount].sad8[3],  
                                 prevMBs[j + i * iWcount].sad16);  
                 }  
         */  
   
         // note: i==horizontal, j==vertical  
         for (i = 0; i < iHcount; i++)  
                 for (j = 0; j < iWcount; j++)  
                 {  
                         MACROBLOCK *pMB = &pMBs[j + i * iWcount];  
                         MACROBLOCK *prevMB = &prevMBs[j + i * iWcount];  
   
                         sad16 = SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,  
                                          j, i, current->motion_flags, current->quant, current->fcode,  
                                          pParam, pMBs, prevMBs, &mv16, &pmv16);  
                         pMB->sad16=sad16;  
296    
297                            pMB->sad16 = SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
298                                                     x, y, current->motion_flags, current->quant, current->fcode,
299                                                     pParam, pMBs, prevMBs, &pMB->mv16, &pMB->pmvs[0]);
300    
301                          /* decide: MODE_INTER or MODE_INTRA                          if (0 < (pMB->sad16 - MV16_INTER_BIAS))
302                             if (dev_intra < sad_inter - 2 * nb) use_intra                          {
303                          */                                  int32_t deviation;
304                                    deviation = dev16(pCurrent->y + x*16 + y*16*pParam->edged_width, pParam->edged_width);
                         deviation = dev16(pCurrent->y + j*16 + i*16*pParam->edged_width, pParam->edged_width);  
305    
306                          if (deviation < (sad16 - INTER_BIAS))                                  if (deviation < (pMB->sad16 - MV16_INTER_BIAS))
307                          {                          {
308                                  pMB->mode = MODE_INTRA;                                  pMB->mode = MODE_INTRA;
309                                  pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = 0;                                          pMB->mv16 = pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = zeroMV;
310                                  pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = 0;                                          pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = 0;
   
                                 pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = 0;  
311    
312                                  iIntra++;                                  iIntra++;
313                                  if(iIntra >= iLimit)                                  if(iIntra >= iLimit)
# Line 340  Line 315 
315    
316                                  continue;                                  continue;
317                          }                          }
318                            }
319    
320                            pmv = pMB->pmvs[0];
321                          if (current->global_flags & XVID_INTER4V)                          if (current->global_flags & XVID_INTER4V)
322                                    if ( (!(current->global_flags & XVID_LUMIMASKING) || pMB->dquant == NO_CHANGE) )
323                          {                          {
324                                  pMB->sad8[0] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                          int32_t sad8 = IMV16X16 * current->quant; if (sad8 < pMB->sad16)
325                                                         2 * j, 2 * i, mv16.x, mv16.y,  
326                                            sad8 += pMB->sad8[0]            = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
327                                                                                                                            2*x, 2*y, pMB->mv16.x, pMB->mv16.y,
328                                                             current->motion_flags, current->quant, current->fcode,                                                             current->motion_flags, current->quant, current->fcode,
329                                                         pParam, pMBs, prevMBs, &pMB->mvs[0], &pMB->pmvs[0]);                                                         pParam, pMBs, prevMBs, &pMB->mvs[0], &pMB->pmvs[0]);
330    
331                                  pMB->sad8[1] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                          if (sad8 < pMB->sad16)
332                                                         2 * j + 1, 2 * i, mv16.x, mv16.y,                                                  sad8 += pMB->sad8[1]    = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
333                                                                                                                            2*x+1, 2*y, pMB->mv16.x, pMB->mv16.y,
334                                                             current->motion_flags, current->quant, current->fcode,                                                             current->motion_flags, current->quant, current->fcode,
335                                                         pParam, pMBs, prevMBs, &pMB->mvs[1], &pMB->pmvs[1]);                                                         pParam, pMBs, prevMBs, &pMB->mvs[1], &pMB->pmvs[1]);
336    
337                                  pMB->sad8[2] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                          if (sad8 < pMB->sad16)
338                                                         2 * j, 2 * i + 1, mv16.x, mv16.y,                                                  sad8 += pMB->sad8[2] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
339                                                                                                                            2*x, 2*y+1, pMB->mv16.x, pMB->mv16.y,
340                                                             current->motion_flags, current->quant, current->fcode,                                                             current->motion_flags, current->quant, current->fcode,
341                                                         pParam, pMBs, prevMBs, &pMB->mvs[2], &pMB->pmvs[2]);                                                         pParam, pMBs, prevMBs, &pMB->mvs[2], &pMB->pmvs[2]);
342    
343                                  pMB->sad8[3] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                          if (sad8 < pMB->sad16)
344                                                         2 * j + 1, 2 * i + 1, mv16.x, mv16.y,                                                  sad8 += pMB->sad8[3]    = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
345                                                                                                                            2*x+1, 2*y+1, pMB->mv16.x, pMB->mv16.y,
346                                                             current->motion_flags, current->quant, current->fcode,                                                             current->motion_flags, current->quant, current->fcode,
347                                                         pParam, pMBs, prevMBs, &pMB->mvs[3], &pMB->pmvs[3]);                                                         pParam, pMBs, prevMBs, &pMB->mvs[3], &pMB->pmvs[3]);
348    
                                 sad8 = pMB->sad8[0] + pMB->sad8[1] + pMB->sad8[2] + pMB->sad8[3];  
                         }  
   
   
349                          /* decide: MODE_INTER or MODE_INTER4V                          /* decide: MODE_INTER or MODE_INTER4V
350                             mpeg4:   if (sad8 < sad16 - nb/2+1) use_inter4v                                                  mpeg4:   if (sad8 < pMB->sad16 - nb/2+1) use_inter4v
351                          */                          */
352    
353                          if (!(current->global_flags & XVID_LUMIMASKING) || pMB->dquant == NO_CHANGE)                                          if (sad8 < pMB->sad16)
                         {  
                                 if (((current->global_flags & XVID_INTER4V)==0) ||  
                                     (sad16 < (sad8 + (int32_t)(IMV16X16 * current->quant))))  
354                                  {                                  {
   
                                         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  
355                                          pMB->mode = MODE_INTER4V;                                          pMB->mode = MODE_INTER4V;
356                          }                              pMB->sad8[0] *= 4;
357                          else                                                  pMB->sad8[1] *= 4;
358                          {                                                  pMB->sad8[2] *= 4;
359                                  sad8 = sad16;                                                  pMB->sad8[3] *= 4;
360                                  pMB->mode = MODE_INTER;                                                  continue;
                                 pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = mv16.x;  
                                 pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = mv16.y;  
                                 pMB->pmvs[0].x = pmv16.x;  
                                 pMB->pmvs[0].y = pmv16.y;  
                         }  
361                  }                  }
362    
 /*      dprintf("*** AFTER ***", pMBs[0].b_mvs[0].x);  
         for (i = 0; i < iHcount; i++)  
                 for (j = 0; j < iWcount; j++)  
                 {  
                         dprintf("   [%i,%i] mode=%i dquant=%i mvs=(%i %i %i %i) sad8=(%i %i %i %i) sad16=(%i)", j,i,  
                                 pMBs[j + i * iWcount].mode,  
                                 pMBs[j + i * iWcount].dquant,  
                                 pMBs[j + i * iWcount].mvs[0],  
                                 pMBs[j + i * iWcount].mvs[1],  
                                 pMBs[j + i * iWcount].mvs[2],  
                                 pMBs[j + i * iWcount].mvs[3],  
                                 pMBs[j + i * iWcount].sad8[0],  
                                 pMBs[j + i * iWcount].sad8[1],  
                                 pMBs[j + i * iWcount].sad8[2],  
                                 pMBs[j + i * iWcount].sad8[3],  
                                 pMBs[j + i * iWcount].sad16);  
363                  }                  }
         */  
364    
365                                    pMB->mode = MODE_INTER;
366                                    pMB->pmvs[0] = pmv; /* pMB->pmvs[1] = pMB->pmvs[2] = pMB->pmvs[3]  are not needed for INTER */
367                                    pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mv16;
368                                    pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = pMB->sad16;
369    
370                    }
371          return 0;          return 0;
372  }  }
373    
 #define MVzero(A) ( ((A).x)==(0) && ((A).y)==(0) )  
   
 #define MVequal(A,B) ( ((A).x)==((B).x) && ((A).y)==((B).y) )  
   
   
374  #define CHECK_MV16_ZERO {\  #define CHECK_MV16_ZERO {\
375    if ( (0 <= max_dx) && (0 >= min_dx) \    if ( (0 <= max_dx) && (0 >= min_dx) \
376      && (0 <= max_dy) && (0 >= min_dy) ) \      && (0 <= max_dy) && (0 >= min_dy) ) \
377    { \    { \
378      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); \
379      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; \  
380      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
381      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \
382  }  }
383    
384  #define NOCHECK_MV16_CANDIDATE(X,Y) { \  #define NOCHECK_MV16_CANDIDATE(X,Y) { \
385      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); \
386      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);\
387      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
388      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
389  }  }
# Line 449  Line 393 
393      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
394    { \    { \
395      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); \
396      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);\
397      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
398      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
399  }  }
# Line 459  Line 403 
403      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
404    { \    { \
405      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); \
406      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);\
407      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
408      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
409  }  }
# Line 469  Line 413 
413      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
414    { \    { \
415      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); \
416      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);\
417      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
418      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
419  }  }
# Line 477  Line 421 
421    
422  #define CHECK_MV8_ZERO {\  #define CHECK_MV8_ZERO {\
423    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); \
424    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);\
425    if (iSAD < iMinSAD) \    if (iSAD < iMinSAD) \
426    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \
427  }  }
# Line 485  Line 429 
429  #define NOCHECK_MV8_CANDIDATE(X,Y) \  #define NOCHECK_MV8_CANDIDATE(X,Y) \
430    { \    { \
431      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); \
432      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);\
433      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
434      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
435  }  }
# Line 495  Line 439 
439      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
440    { \    { \
441      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); \
442      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);\
443      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
444      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
445  }  }
# Line 505  Line 449 
449      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
450    { \    { \
451      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); \
452      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);\
453      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
454      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
455  }  }
# Line 515  Line 459 
459      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
460    { \    { \
461      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); \
462      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);\
463      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
464      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
465  }  }
# Line 782  Line 726 
726          return iMinSAD;          return iMinSAD;
727  }  }
728    
729    int32_t AdvDiamond16_MainSearch(
730            const uint8_t * const pRef,
731            const uint8_t * const pRefH,
732            const uint8_t * const pRefV,
733            const uint8_t * const pRefHV,
734            const uint8_t * const cur,
735            const int x, const int y,
736            int32_t startx, int32_t starty,
737            int32_t iMinSAD,
738            VECTOR * const currMV,
739            const VECTOR * const pmv,
740            const int32_t min_dx, const int32_t max_dx,
741            const int32_t min_dy, const int32_t max_dy,
742            const int32_t iEdgedWidth,
743            const int32_t iDiamondSize,
744            const int32_t iFcode,
745            const int32_t iQuant,
746            int iDirection)
747    {
748    
749            int32_t iSAD;
750    
751    /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
752    
753            if (iDirection)
754            {
755                    CHECK_MV16_CANDIDATE(startx-iDiamondSize, starty);
756                    CHECK_MV16_CANDIDATE(startx+iDiamondSize, starty);
757                    CHECK_MV16_CANDIDATE(startx, starty-iDiamondSize);
758                    CHECK_MV16_CANDIDATE(startx, starty+iDiamondSize);
759            }
760            else
761            {
762                    int bDirection = 1+2+4+8;
763                    do
764                    {
765                            iDirection = 0;
766                            if (bDirection&1) //we only want to check left if we came from the right (our last motion was to the left, up-left or down-left)
767                                    CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize,starty,1);
768    
769                            if (bDirection&2)
770                                    CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize,starty,2);
771    
772                            if (bDirection&4)
773                                    CHECK_MV16_CANDIDATE_DIR(startx,starty-iDiamondSize,4);
774    
775                            if (bDirection&8)
776                                    CHECK_MV16_CANDIDATE_DIR(startx,starty+iDiamondSize,8);
777    
778                            /* now we're doing diagonal checks near our candidate */
779    
780                            if (iDirection) //checking if anything found
781                            {
782                                    bDirection = iDirection;
783                                    iDirection = 0;
784                                    startx=currMV->x; starty=currMV->y;
785                                    if (bDirection & 3) //our candidate is left or right
786                                    {
787                                            CHECK_MV16_CANDIDATE_DIR(startx,starty+iDiamondSize, 8);
788                                            CHECK_MV16_CANDIDATE_DIR(startx,starty-iDiamondSize, 4);
789                                    }
790                                    else // what remains here is up or down
791                                    {
792                                            CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty, 2);
793                                            CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty, 1);
794                                    }
795    
796                                    if (iDirection)
797                                    {       bDirection+=iDirection;
798                                            startx=currMV->x; starty=currMV->y;
799                                    }
800                            }
801                            else //about to quit, eh? not so fast....
802                            {
803                                    switch (bDirection)
804                                    {
805                                    case 2:
806                                            CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);
807                                            CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);
808                                            break;
809                                    case 1:
810                                            CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);
811                                            CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);
812                                            break;
813                                    case 2+4:
814                                            CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);
815                                            CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);
816                                            CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);
817                                            break;
818                                    case 4:
819                                            CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);
820                                            CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);
821                                            break;
822                                    case 8:
823                                            CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);
824                                            CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);
825                                            break;
826                                    case 1+4:
827                                            CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);
828                                            CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);
829                                            CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);
830                                            break;
831                                    case 2+8:
832                                            CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);
833                                            CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);
834                                            CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);
835                                            break;
836                                    case 1+8:
837                                            CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);
838                                            CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);
839                                            CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);
840                                            break;
841                                    default: //1+2+4+8 == we didn't find anything at all
842                                            CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);
843                                            CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);
844                                            CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);
845                                            CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);
846                                            break;
847                                    }
848                                    if (!iDirection) break; //ok, the end. really
849                                    else
850                                    {       bDirection=iDirection;
851                                            startx=currMV->x; starty=currMV->y;
852                                    }
853                            }
854                    }
855                    while (1); //forever
856            }
857            return iMinSAD;
858    }
859    
860    int32_t AdvDiamond8_MainSearch(
861            const uint8_t * const pRef,
862            const uint8_t * const pRefH,
863            const uint8_t * const pRefV,
864            const uint8_t * const pRefHV,
865            const uint8_t * const cur,
866            const int x, const int y,
867            int32_t startx, int32_t starty,
868            int32_t iMinSAD,
869            VECTOR * const currMV,
870            const VECTOR * const pmv,
871            const int32_t min_dx, const int32_t max_dx,
872            const int32_t min_dy, const int32_t max_dy,
873            const int32_t iEdgedWidth,
874            const int32_t iDiamondSize,
875            const int32_t iFcode,
876            const int32_t iQuant,
877            int iDirection)
878    {
879    
880            int32_t iSAD;
881    
882    /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
883    
884            if (iDirection)
885            {
886                    CHECK_MV8_CANDIDATE(startx-iDiamondSize, starty);
887                    CHECK_MV8_CANDIDATE(startx+iDiamondSize, starty);
888                    CHECK_MV8_CANDIDATE(startx, starty-iDiamondSize);
889                    CHECK_MV8_CANDIDATE(startx, starty+iDiamondSize);
890            }
891            else
892            {
893                    int bDirection = 1+2+4+8;
894                    do
895                    {
896                            iDirection = 0;
897                            if (bDirection&1) //we only want to check left if we came from the right (our last motion was to the left, up-left or down-left)
898                                    CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize,starty,1);
899    
900                            if (bDirection&2)
901                                    CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize,starty,2);
902    
903                            if (bDirection&4)
904                                    CHECK_MV8_CANDIDATE_DIR(startx,starty-iDiamondSize,4);
905    
906                            if (bDirection&8)
907                                    CHECK_MV8_CANDIDATE_DIR(startx,starty+iDiamondSize,8);
908    
909                            /* now we're doing diagonal checks near our candidate */
910    
911                            if (iDirection) //checking if anything found
912                            {
913                                    bDirection = iDirection;
914                                    iDirection = 0;
915                                    startx=currMV->x; starty=currMV->y;
916                                    if (bDirection & 3) //our candidate is left or right
917                                    {
918                                            CHECK_MV8_CANDIDATE_DIR(startx,starty+iDiamondSize, 8);
919                                            CHECK_MV8_CANDIDATE_DIR(startx,starty-iDiamondSize, 4);
920                                    }
921                                    else // what remains here is up or down
922                                    {
923                                            CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty, 2);
924                                            CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty, 1);
925                                    }
926    
927                                    if (iDirection)
928                                    {       bDirection+=iDirection;
929                                            startx=currMV->x; starty=currMV->y;
930                                    }
931                            }
932                            else //about to quit, eh? not so fast....
933                            {
934                                    switch (bDirection)
935                                    {
936                                    case 2:
937                                            CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);
938                                            CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);
939                                            break;
940                                    case 1:
941                                            CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);
942                                            CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);
943                                            break;
944                                    case 2+4:
945                                            CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);
946                                            CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);
947                                            CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);
948                                            break;
949                                    case 4:
950                                            CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);
951                                            CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);
952                                            break;
953                                    case 8:
954                                            CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);
955                                            CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);
956                                            break;
957                                    case 1+4:
958                                            CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);
959                                            CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);
960                                            CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);
961                                            break;
962                                    case 2+8:
963                                            CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);
964                                            CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);
965                                            CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);
966                                            break;
967                                    case 1+8:
968                                            CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);
969                                            CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);
970                                            CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);
971                                            break;
972                                    default: //1+2+4+8 == we didn't find anything at all
973                                            CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);
974                                            CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);
975                                            CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);
976                                            CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);
977                                            break;
978                                    }
979                                    if (!(iDirection)) break; //ok, the end. really
980                                    else
981                                    {       bDirection=iDirection;
982                                            startx=currMV->x; starty=currMV->y;
983                                    }
984                            }
985                    }
986                    while (1); //forever
987            }
988            return iMinSAD;
989    }
990    
991    
992  int32_t Full8_MainSearch(  int32_t Full8_MainSearch(
993                                          const uint8_t * const pRef,                                          const uint8_t * const pRef,
994                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
# Line 890  Line 1097 
1097          VECTOR pmv[4];          VECTOR pmv[4];
1098          int32_t psad[4];          int32_t psad[4];
1099    
1100          const MACROBLOCK * const pMB = pMBs + x + y * iWcount;          MainSearch16FuncPtr MainSearchPtr;
1101    
1102    //      const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
1103          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
1104    
1105          static int32_t threshA,threshB;          static int32_t threshA,threshB;
# Line 930  Line 1139 
1139    
1140          iFound=0;          iFound=0;
1141    
 /* 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],prevMB->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;  
   
1142  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
1143     MinSAD=SAD     MinSAD=SAD
1144     If Motion Vector equal to Previous frame motion vector     If Motion Vector equal to Previous frame motion vector
# Line 957  Line 1146 
1146     If SAD<=256 goto Step 10.     If SAD<=256 goto Step 10.
1147  */  */
1148    
   
 // Prepare for main loop  
   
1149          *currMV=pmv[0];         /* current best := prediction */          *currMV=pmv[0];         /* current best := prediction */
1150          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16 ))
1151          {       /* This should NOT be necessary! */          {       /* This should NOT be necessary! */
# Line 987  Line 1173 
1173          iMinSAD = sad16( cur,          iMinSAD = sad16( cur,
1174                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),
1175                           iEdgedWidth, MV_MAX_ERROR);                           iEdgedWidth, MV_MAX_ERROR);
1176          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);
1177    
1178          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )
1179          {          {
1180                    if (iMinSAD < 2*iQuant) // high chances for SKIP-mode
1181                    {
1182                            if (!MVzero(*currMV))
1183                            {
1184                                    iMinSAD += MV16_00_BIAS;
1185                                    CHECK_MV16_ZERO;                // (0,0) saves space for letterboxed pictures
1186                                    iMinSAD -= MV16_00_BIAS;
1187                            }
1188                    }
1189    
1190                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1191                          goto PMVfast16_Terminate_without_Refine;                          goto PMVfast16_Terminate_without_Refine;
# Line 998  Line 1193 
1193                          goto PMVfast16_Terminate_with_Refine;                          goto PMVfast16_Terminate_with_Refine;
1194          }          }
1195    
1196    
1197    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
1198       vector of the median.
1199       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1200    */
1201    
1202            if ((bPredEq) && (MVequal(pmv[0],prevMB->mvs[0]) ) )
1203                    iFound=2;
1204    
1205    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
1206       Otherwise select large Diamond Search.
1207    */
1208    
1209            if ( (!MVzero(pmv[0])) || (threshB<1536) || (bPredEq) )
1210                    iDiamondSize=1; // halfpel!
1211            else
1212                    iDiamondSize=2; // halfpel!
1213    
1214            if (!(MotionFlags & PMV_HALFPELDIAMOND16) )
1215                    iDiamondSize*=2;
1216    
1217  /*  /*
1218     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.
1219     Also calculate (0,0) but do not subtract offset.     Also calculate (0,0) but do not subtract offset.
1220     Let MinSAD be the smallest SAD up to this point.     Let MinSAD be the smallest SAD up to this point.
1221     If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
1222  */  */
1223    
1224  // (0,0) is always possible  // (0,0) is always possible
1225    
1226            if (!MVzero(pmv[0]))
1227          CHECK_MV16_ZERO;          CHECK_MV16_ZERO;
1228    
1229  // previous frame MV is always possible  // previous frame MV is always possible
1230    
1231            if (!MVzero(prevMB->mvs[0]))
1232            if (!MVequal(prevMB->mvs[0],pmv[0]))
1233          CHECK_MV16_CANDIDATE(prevMB->mvs[0].x,prevMB->mvs[0].y);          CHECK_MV16_CANDIDATE(prevMB->mvs[0].x,prevMB->mvs[0].y);
1234    
1235  // left neighbour, if allowed  // left neighbour, if allowed
1236          if (x != 0)  
1237            if (!MVzero(pmv[1]))
1238            if (!MVequal(pmv[1],prevMB->mvs[0]))
1239            if (!MVequal(pmv[1],pmv[0]))
1240          {          {
1241                  if (!(MotionFlags & PMV_HALFPEL16 ))                  if (!(MotionFlags & PMV_HALFPEL16 ))
1242                  {       pmv[1].x = EVEN(pmv[1].x);                  {       pmv[1].x = EVEN(pmv[1].x);
1243                  pmv[1].y = EVEN(pmv[1].y);                  pmv[1].y = EVEN(pmv[1].y);
1244                  }                  }
1245    
1246                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1247          }          }
1248    
1249  // top neighbour, if allowed  // top neighbour, if allowed
1250          if (y != 0)          if (!MVzero(pmv[2]))
1251            if (!MVequal(pmv[2],prevMB->mvs[0]))
1252            if (!MVequal(pmv[2],pmv[0]))
1253            if (!MVequal(pmv[2],pmv[1]))
1254          {          {
1255                  if (!(MotionFlags & PMV_HALFPEL16 ))                  if (!(MotionFlags & PMV_HALFPEL16 ))
1256                  {       pmv[2].x = EVEN(pmv[2].x);                  {       pmv[2].x = EVEN(pmv[2].x);
# Line 1032  Line 1259 
1259                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1260    
1261  // top right neighbour, if allowed  // top right neighbour, if allowed
1262                  if ((uint32_t)x != (iWcount-1))                  if (!MVzero(pmv[3]))
1263                    if (!MVequal(pmv[3],prevMB->mvs[0]))
1264                    if (!MVequal(pmv[3],pmv[0]))
1265                    if (!MVequal(pmv[3],pmv[1]))
1266                    if (!MVequal(pmv[3],pmv[2]))
1267                  {                  {
1268                          if (!(MotionFlags & PMV_HALFPEL16 ))                          if (!(MotionFlags & PMV_HALFPEL16 ))
1269                          {       pmv[3].x = EVEN(pmv[3].x);                          {       pmv[3].x = EVEN(pmv[3].x);
# Line 1042  Line 1273 
1273                  }                  }
1274          }          }
1275    
1276            if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96)*/ )
1277                    iMinSAD -= MV16_00_BIAS;
1278    
1279    
1280  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
1281     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.
1282  */  */
# Line 1065  Line 1300 
1300     Refine by using small diamond and goto step 10.     Refine by using small diamond and goto step 10.
1301  */  */
1302    
1303            if (MotionFlags & PMV_USESQUARES16)
1304                    MainSearchPtr = Square16_MainSearch;
1305            else
1306                    if (MotionFlags & PMV_ADVANCEDDIAMOND16)
1307                            MainSearchPtr = AdvDiamond16_MainSearch;
1308                    else
1309                            MainSearchPtr = Diamond16_MainSearch;
1310    
1311          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1312    
1313  /* 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 */
1314          iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1315                                            x, y,                                            x, y,
1316                                            currMV->x, currMV->y, iMinSAD, &newMV,                                            currMV->x, currMV->y, iMinSAD, &newMV,
1317                                            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 1084  Line 1327 
1327  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1328    
1329                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0],backupMV)) )
1330                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1331                                                            x, y,                                                            x, y,
1332                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1333                                                            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 1097  Line 1340 
1340                  }                  }
1341    
1342                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1343                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1344                                                            x, y,                                                            x, y,
1345                                                            0, 0, iMinSAD, &newMV,                                                            0, 0, iMinSAD, &newMV,
1346                                                            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 1260  Line 1503 
1503          int32_t psad[4];          int32_t psad[4];
1504          VECTOR newMV;          VECTOR newMV;
1505          VECTOR backupMV;          VECTOR backupMV;
1506            VECTOR startMV;
1507    
1508          const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;  //      const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1509          const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;          const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;
1510    
1511          static int32_t threshA,threshB;          static int32_t threshA,threshB;
1512          int32_t iFound,bPredEq;          int32_t iFound,bPredEq;
1513          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
1514    
1515          int32_t iSubBlock = ((y&1)<<1) + (x&1);          int32_t iSubBlock = (y&1)+(y&1) + (x&1);
1516    
1517            MainSearch8FuncPtr MainSearchPtr;
1518    
1519            /* Init variables */
1520            startMV.x = start_x;
1521            startMV.y = start_y;
1522    
1523  /* Get maximum range */  /* Get maximum range */
1524          get_range(&min_dx, &max_dx, &min_dy, &max_dy,          get_range(&min_dx, &max_dx, &min_dy, &max_dy,
1525                    x, y, 8, iWidth, iHeight, iFcode);                    x, y, 8, iWidth, iHeight, iFcode);
1526    
 /* we work with abs. MVs, not relative to prediction, so range is relative to 0,0 */  
   
1527          if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))          if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))
1528          { min_dx = EVEN(min_dx);          { min_dx = EVEN(min_dx);
1529          max_dx = EVEN(max_dx);          max_dx = EVEN(max_dx);
# Line 1303  Line 1551 
1551    
1552          iFound=0;          iFound=0;
1553    
 /* 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;  
   
1554  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
1555     MinSAD=SAD     MinSAD=SAD
1556     If Motion Vector equal to Previous frame motion vector     If Motion Vector equal to Previous frame motion vector
# Line 1333  Line 1561 
1561    
1562  // Prepare for main loop  // Prepare for main loop
1563    
1564          currMV->x=start_x;              /* start with mv16 */  //      if (MotionFlags & PMV_USESQUARES8)
1565          currMV->y=start_y;  //              MainSearchPtr = Square8_MainSearch;
1566    //      else
1567    
1568            if (MotionFlags & PMV_ADVANCEDDIAMOND8)
1569                    MainSearchPtr = AdvDiamond8_MainSearch;
1570            else
1571                    MainSearchPtr = Diamond8_MainSearch;
1572    
1573    
1574            *currMV = startMV;
1575    
1576          iMinSAD = sad8( cur,          iMinSAD = sad8( cur,
1577                          get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),                          get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),
1578                          iEdgedWidth);                          iEdgedWidth);
1579          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);
1580    
1581          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,pMB->mvs[iSubBlock])) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,prevMB->mvs[iSubBlock]))
1582                                    && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )
1583          {          {
1584                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1585                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
# Line 1349  Line 1587 
1587                          goto PMVfast8_Terminate_with_Refine;                          goto PMVfast8_Terminate_with_Refine;
1588          }          }
1589    
1590    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
1591       vector of the median.
1592       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1593    */
1594    
1595            if ((bPredEq) && (MVequal(pmv[0],prevMB->mvs[iSubBlock]) ) )
1596                    iFound=2;
1597    
1598    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
1599       Otherwise select large Diamond Search.
1600    */
1601    
1602            if ( (!MVzero(pmv[0])) || (threshB<1536/4) || (bPredEq) )
1603                    iDiamondSize=1; // 1 halfpel!
1604            else
1605                    iDiamondSize=2; // 2 halfpel = 1 full pixel!
1606    
1607            if (!(MotionFlags & PMV_HALFPELDIAMOND8) )
1608                    iDiamondSize*=2;
1609    
1610    
1611  /*  /*
1612     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.
1613     Also calculate (0,0) but do not subtract offset.     Also calculate (0,0) but do not subtract offset.
1614     Let MinSAD be the smallest SAD up to this point.     Let MinSAD be the smallest SAD up to this point.
1615     If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
1616  */  */
1617    
1618  // the prediction might be even better than mv16  // the median prediction might be even better than mv16
1619    
1620            if (!MVequal(pmv[0],startMV))
1621          CHECK_MV8_CANDIDATE(pmv[0].x,pmv[0].y);          CHECK_MV8_CANDIDATE(pmv[0].x,pmv[0].y);
1622    
1623  // (0,0) is always possible  // (0,0) if needed
1624            if (!MVzero(pmv[0]))
1625            if (!MVzero(startMV))
1626          CHECK_MV8_ZERO;          CHECK_MV8_ZERO;
1627    
1628  // previous frame MV is always possible  // previous frame MV if needed
1629          CHECK_MV8_CANDIDATE(pMB->mvs[iSubBlock].x,pMB->mvs[iSubBlock].y);          if (!MVzero(prevMB->mvs[iSubBlock]))
1630            if (!MVequal(prevMB->mvs[iSubBlock],startMV))
1631            if (!MVequal(prevMB->mvs[iSubBlock],pmv[0]))
1632            CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);
1633    
1634  // left neighbour, if allowed          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[iSubBlock]) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )
1635          if (psad[1] != MV_MAX_ERROR)          {
1636                    if (MotionFlags & PMV_QUICKSTOP16)
1637                            goto PMVfast8_Terminate_without_Refine;
1638                    if (MotionFlags & PMV_EARLYSTOP16)
1639                            goto PMVfast8_Terminate_with_Refine;
1640            }
1641    
1642    
1643    // left neighbour, if allowed and needed
1644            if (!MVzero(pmv[1]))
1645            if (!MVequal(pmv[1],startMV))
1646            if (!MVequal(pmv[1],prevMB->mvs[iSubBlock]))
1647            if (!MVequal(pmv[1],pmv[0]))
1648          {          {
1649                  if (!(MotionFlags & PMV_HALFPEL8 ))                  if (!(MotionFlags & PMV_HALFPEL8 ))
1650                  {       pmv[1].x = EVEN(pmv[1].x);                  {       pmv[1].x = EVEN(pmv[1].x);
# Line 1376  Line 1653 
1653                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
1654          }          }
1655    
1656  // top neighbour, if allowed  // top neighbour, if allowed and needed
1657          if (psad[2] != MV_MAX_ERROR)          if (!MVzero(pmv[2]))
1658            if (!MVequal(pmv[2],startMV))
1659            if (!MVequal(pmv[2],prevMB->mvs[iSubBlock]))
1660            if (!MVequal(pmv[2],pmv[0]))
1661            if (!MVequal(pmv[2],pmv[1]))
1662          {          {
1663                  if (!(MotionFlags & PMV_HALFPEL8 ))                  if (!(MotionFlags & PMV_HALFPEL8 ))
1664                  {       pmv[2].x = EVEN(pmv[2].x);                  {       pmv[2].x = EVEN(pmv[2].x);
# Line 1385  Line 1666 
1666                  }                  }
1667                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
1668    
1669  // top right neighbour, if allowed  // top right neighbour, if allowed and needed
1670                  if (psad[3] != MV_MAX_ERROR)          if (!MVzero(pmv[3]))
1671            if (!MVequal(pmv[3],startMV))
1672            if (!MVequal(pmv[3],prevMB->mvs[iSubBlock]))
1673            if (!MVequal(pmv[3],pmv[0]))
1674            if (!MVequal(pmv[3],pmv[1]))
1675            if (!MVequal(pmv[3],pmv[2]))
1676                  {                  {
1677                          if (!(MotionFlags & PMV_HALFPEL8 ))                          if (!(MotionFlags & PMV_HALFPEL8 ))
1678                          {       pmv[3].x = EVEN(pmv[3].x);                          {       pmv[3].x = EVEN(pmv[3].x);
# Line 1396  Line 1682 
1682                  }                  }
1683          }          }
1684    
1685            if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1686                    iMinSAD -= MV8_00_BIAS;
1687    
1688    
1689  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
1690     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.
1691  */  */
1692    
1693          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[iSubBlock]) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[iSubBlock]) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )
1694          {          {
1695                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1696                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
# Line 1421  Line 1711 
1711          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1712    
1713  /* 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 */
1714          iSAD = Diamond8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1715                                           x, y,                                           x, y,
1716                                           currMV->x, currMV->y, iMinSAD, &newMV,                                           currMV->x, currMV->y, iMinSAD, &newMV,
1717                                           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 1437  Line 1727 
1727  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1728    
1729                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0],backupMV)) )
1730                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1731                                                            x, y,                                                            x, y,
1732                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1733                                                            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 1450  Line 1740 
1740                  }                  }
1741    
1742                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1743                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1744                                                            x, y,                                                            x, y,
1745                                                            0, 0, iMinSAD, &newMV,                                                            0, 0, iMinSAD, &newMV,
1746                                                            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 1519  Line 1809 
1809          int32_t psad[8];          int32_t psad[8];
1810    
1811          static MACROBLOCK * oldMBs = NULL;          static MACROBLOCK * oldMBs = NULL;
1812          const MACROBLOCK * const pMB = pMBs + x + y * iWcount;  //      const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
1813          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
1814          MACROBLOCK * oldMB = NULL;          MACROBLOCK * oldMB = NULL;
1815    
# Line 1527  Line 1817 
1817          int32_t bPredEq;          int32_t bPredEq;
1818          int32_t iMinSAD,iSAD=9999;          int32_t iMinSAD,iSAD=9999;
1819    
1820          MainSearch16FuncPtr EPZSMainSearchPtr;          MainSearch16FuncPtr MainSearchPtr;
1821    
1822          if (oldMBs == NULL)          if (oldMBs == NULL)
1823          {       oldMBs = (MACROBLOCK*) calloc(1,iWcount*iHcount*sizeof(MACROBLOCK));          {       oldMBs = (MACROBLOCK*) calloc(iWcount*iHcount,sizeof(MACROBLOCK));
1824                  fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));  //              fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));
1825          }          }
1826          oldMB = oldMBs + x + y * iWcount;          oldMB = oldMBs + x + y * iWcount;
1827    
# Line 1539  Line 1829 
1829          get_range(&min_dx, &max_dx, &min_dy, &max_dy,          get_range(&min_dx, &max_dx, &min_dy, &max_dy,
1830                          x, y, 16, iWidth, iHeight, iFcode);                          x, y, 16, iWidth, iHeight, iFcode);
1831    
 /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */  
   
1832          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16 ))
1833          { min_dx = EVEN(min_dx);          { min_dx = EVEN(min_dx);
1834            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
# Line 1580  Line 1868 
1868          iMinSAD = sad16( cur,          iMinSAD = sad16( cur,
1869                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),
1870                  iEdgedWidth, MV_MAX_ERROR);                  iEdgedWidth, MV_MAX_ERROR);
1871          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);
1872    
1873  // thresh1 is fixed to 256  // thresh1 is fixed to 256
1874          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV, prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )
1875                  {                  {
1876                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
1877                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
# Line 1594  Line 1882 
1882  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
1883    
1884  // previous frame MV  // previous frame MV
1885          CHECK_MV16_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);          CHECK_MV16_CANDIDATE(prevMB->mvs[0].x,prevMB->mvs[0].y);
1886    
1887  // set threshhold based on Min of Prediction and SAD of collocated block  // set threshhold based on Min of Prediction and SAD of collocated block
1888  // 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 1650  Line 1938 
1938  */  */
1939    
1940          if ( (iMinSAD <= thresh2)          if ( (iMinSAD <= thresh2)
1941                  || ( MVequal(*currMV,pMB->mvs[0]) && ((uint32_t)iMinSAD <= prevMB->sad16) ) )                  || ( MVequal(*currMV,prevMB->mvs[0]) && ((uint32_t)iMinSAD <= prevMB->sad16) ) )
1942                  {                  {
1943                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
1944                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
# Line 1660  Line 1948 
1948    
1949  /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/  /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/
1950    
1951          backupMV = pMB->mvs[0];                 // last MV          backupMV = prevMB->mvs[0];              // collocated MV
1952          backupMV.x += (pMB->mvs[0].x - oldMB->mvs[0].x );       // acceleration X          backupMV.x += (prevMB->mvs[0].x - oldMB->mvs[0].x );    // acceleration X
1953          backupMV.y += (pMB->mvs[0].y - oldMB->mvs[0].y );       // acceleration Y          backupMV.y += (prevMB->mvs[0].y - oldMB->mvs[0].y );    // acceleration Y
1954    
1955          CHECK_MV16_CANDIDATE(backupMV.x,backupMV.y);          CHECK_MV16_CANDIDATE(backupMV.x,backupMV.y);
1956    
1957  // left neighbour  // left neighbour
1958          if (x != 0)          if (x != 0)
1959                  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);
1960    
1961  // top neighbour  // top neighbour
1962          if (y != 0)          if (y != 0)
1963                  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);
1964    
1965  // 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
1966    
1967          if ((uint32_t)x != iWcount-1)          if ((uint32_t)x != iWcount-1)
1968                  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);
1969    
1970  // bottom neighbour, dito  // bottom neighbour, dito
1971          if ((uint32_t)y != iHcount-1)          if ((uint32_t)y != iHcount-1)
1972                  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);
1973    
1974  /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */  /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */
1975          if (iMinSAD <= thresh2)          if (iMinSAD <= thresh2)
# Line 1696  Line 1984 
1984    
1985          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1986    
1987  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */          if (MotionFlags & PMV_USESQUARES8)
1988                    MainSearchPtr = Square16_MainSearch;
1989            else
1990    
1991          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_ADVANCEDDIAMOND8)
1992                  EPZSMainSearchPtr = Square16_MainSearch;                  MainSearchPtr = AdvDiamond16_MainSearch;
1993          else          else
1994                  EPZSMainSearchPtr = Diamond16_MainSearch;                  MainSearchPtr = Diamond16_MainSearch;
1995    
1996          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
1997    
1998            iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1999                          x, y,                          x, y,
2000                          currMV->x, currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,                          currMV->x, currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2001                          2, iFcode, iQuant, 0);                          2, iFcode, iQuant, 0);
# Line 1721  Line 2013 
2013    
2014                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0],backupMV)) )
2015                  {                  {
2016                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
2017                                  x, y,                                  x, y,
2018                                  pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                  pmv[0].x, pmv[0].y, iMinSAD, &newMV,
2019                                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);                                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
# Line 1735  Line 2027 
2027    
2028                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
2029                  {                  {
2030                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
2031                                  x, y,                                  x, y,
2032                          0, 0, iMinSAD, &newMV,                          0, 0, iMinSAD, &newMV,
2033                          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);
2034    
2035                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD)
2036                          {                          {
# Line 1759  Line 2051 
2051    
2052  EPZS16_Terminate_without_Refine:  EPZS16_Terminate_without_Refine:
2053    
2054          *oldMB = *pMB;          *oldMB = *prevMB;
2055    
2056          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - pmv[0].x;
2057          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - pmv[0].y;
# Line 1784  Line 2076 
2076                                          VECTOR * const currMV,                                          VECTOR * const currMV,
2077                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
2078  {  {
2079    /* Please not that EPZS might not be a good choice for 8x8-block motion search ! */
2080    
2081      const uint32_t iWcount = pParam->mb_width;      const uint32_t iWcount = pParam->mb_width;
2082          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
2083          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
# Line 1806  Line 2100 
2100    
2101          const   int32_t iSubBlock = ((y&1)<<1) + (x&1);          const   int32_t iSubBlock = ((y&1)<<1) + (x&1);
2102    
2103          const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;  //      const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
2104          const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;          const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;
2105    
2106          int32_t bPredEq;          int32_t bPredEq;
2107          int32_t iMinSAD,iSAD=9999;          int32_t iMinSAD,iSAD=9999;
2108    
2109          MainSearch8FuncPtr EPZSMainSearchPtr;          MainSearch8FuncPtr MainSearchPtr;
2110    
2111  /* Get maximum range */  /* Get maximum range */
2112          get_range(&min_dx, &max_dx, &min_dy, &max_dy,          get_range(&min_dx, &max_dx, &min_dy, &max_dy,
# Line 1861  Line 2155 
2155          iMinSAD = sad8( cur,          iMinSAD = sad8( cur,
2156                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),
2157                  iEdgedWidth);                  iEdgedWidth);
2158          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);
2159    
2160    
2161  // thresh1 is fixed to 256  // thresh1 is fixed to 256
# Line 1875  Line 2169 
2169    
2170  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
2171    
 // previous frame MV  
         CHECK_MV8_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);  
2172    
2173  // MV=(0,0) is often a good choice  // MV=(0,0) is often a good choice
   
2174          CHECK_MV8_ZERO;          CHECK_MV8_ZERO;
2175    
2176    // previous frame MV
2177            CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);
2178    
2179    // left neighbour, if allowed
2180            if (psad[1] != MV_MAX_ERROR)
2181            {
2182                    if (!(MotionFlags & PMV_HALFPEL8 ))
2183                    {       pmv[1].x = EVEN(pmv[1].x);
2184                            pmv[1].y = EVEN(pmv[1].y);
2185                    }
2186                    CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
2187            }
2188    
2189    // top neighbour, if allowed
2190            if (psad[2] != MV_MAX_ERROR)
2191            {
2192                    if (!(MotionFlags & PMV_HALFPEL8 ))
2193                    {       pmv[2].x = EVEN(pmv[2].x);
2194                            pmv[2].y = EVEN(pmv[2].y);
2195                    }
2196                    CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
2197    
2198    // top right neighbour, if allowed
2199                    if (psad[3] != MV_MAX_ERROR)
2200                    {
2201                            if (!(MotionFlags & PMV_HALFPEL8 ))
2202                            {       pmv[3].x = EVEN(pmv[3].x);
2203                                    pmv[3].y = EVEN(pmv[3].y);
2204                            }
2205                            CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);
2206                    }
2207            }
2208    
2209    /*  // this bias is zero anyway, at the moment!
2210    
2211            if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) ) // && (iMinSAD <= iQuant * 96)
2212                    iMinSAD -= MV8_00_BIAS;
2213    
2214    */
2215    
2216  /* Terminate if MinSAD <= T_2  /* Terminate if MinSAD <= T_2
2217     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]
2218  */  */
# Line 1894  Line 2225 
2225                                  goto EPZS8_Terminate_with_Refine;                                  goto EPZS8_Terminate_with_Refine;
2226                  }                  }
2227    
2228  /************ (if Diamond Search)  **************/  /************ (Diamond Search)  **************/
2229    
2230          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
2231    
2232          if (!(MotionFlags & PMV_HALFPELDIAMOND8))          if (!(MotionFlags & PMV_HALFPELDIAMOND8))
2233                  iDiamondSize *= 2;                  iDiamondSize *= 2;
2234    
2235  /* 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 */
2236    
2237    // there is no EPZS^2 for inter4v at the moment
2238    
2239  //      if (MotionFlags & PMV_USESQUARES8)  //      if (MotionFlags & PMV_USESQUARES8)
2240  //              EPZSMainSearchPtr = Square8_MainSearch;  //              MainSearchPtr = Square8_MainSearch;
2241  //      else  //      else
                 EPZSMainSearchPtr = Diamond8_MainSearch;  
2242    
2243          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,          if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2244                    MainSearchPtr = AdvDiamond8_MainSearch;
2245            else
2246                    MainSearchPtr = Diamond8_MainSearch;
2247    
2248            iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
2249                  x, y,                  x, y,
2250                  currMV->x, currMV->y, iMinSAD, &newMV,                  currMV->x, currMV->y, iMinSAD, &newMV,
2251                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2252                  iDiamondSize, iFcode, iQuant, 00);                  iDiamondSize, iFcode, iQuant, 0);
2253    
2254    
2255          if (iSAD < iMinSAD)          if (iSAD < iMinSAD)
# Line 1927  Line 2264 
2264    
2265                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0],backupMV)) )
2266                  {                  {
2267                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
2268                                  x, y,                                  x, y,
2269                          pmv[0].x, pmv[0].y, iMinSAD, &newMV,                          pmv[0].x, pmv[0].y, iMinSAD, &newMV,
2270                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);
# Line 1941  Line 2278 
2278    
2279                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
2280                  {                  {
2281                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
2282                                  x, y,                                  x, y,
2283                          0, 0, iMinSAD, &newMV,                          0, 0, iMinSAD, &newMV,
2284                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);
# Line 1979  Line 2316 
2316  // TODO: need to incorporate prediction here (eg. sad += calc_delta_16)  // TODO: need to incorporate prediction here (eg. sad += calc_delta_16)
2317  ***************************************************************/  ***************************************************************/
2318    
2319  /*  
2320  void MotionEstimationBVOP(  void MotionEstimationBVOP(
2321                          MBParam * const pParam,                          MBParam * const pParam,
2322                          FRAMEINFO * const frame,                          FRAMEINFO * const frame,
# Line 2001  Line 2338 
2338      const uint32_t mb_height = pParam->mb_height;      const uint32_t mb_height = pParam->mb_height;
2339          const int32_t edged_width = pParam->edged_width;          const int32_t edged_width = pParam->edged_width;
2340    
2341          int32_t i,j;          uint32_t i,j;
2342    
2343          int32_t f_sad16;          int32_t f_sad16;
2344          int32_t b_sad16;          int32_t b_sad16;
# Line 2025  Line 2362 
2362                                  && b_mb->mvs[0].x == 0                                  && b_mb->mvs[0].x == 0
2363                                  && b_mb->mvs[0].y == 0)                                  && b_mb->mvs[0].y == 0)
2364                          {                          {
2365                                  mb->mode = MB_IGNORE;                                  mb->mode = MODE_NOT_CODED;
2366                                  mb->mvs[0].x = 0;                                  mb->mvs[0].x = 0;
2367                                  mb->mvs[0].y = 0;                                  mb->mvs[0].y = 0;
2368                                  mb->b_mvs[0].x = 0;                                  mb->b_mvs[0].x = 0;
# Line 2040  Line 2377 
2377                                                  i, j,                                                  i, j,
2378                                                  frame->motion_flags,  frame->quant, frame->fcode,                                                  frame->motion_flags,  frame->quant, frame->fcode,
2379                                                  pParam,                                                  pParam,
2380                                                  f_mbs,                                                  f_mbs, f_mbs /* todo */,
2381                                                  &mb->mvs[0], &pmv_dontcare);    // ignore pmv                                                  &mb->mvs[0], &pmv_dontcare);    // ignore pmv
2382    
2383                          // backward search                          // backward search
# Line 2049  Line 2386 
2386                                                  i, j,                                                  i, j,
2387                                                  frame->motion_flags,  frame->quant, frame->bcode,                                                  frame->motion_flags,  frame->quant, frame->bcode,
2388                                                  pParam,                                                  pParam,
2389                                                  b_mbs,                                                  b_mbs, b_mbs, /* todo */
2390                                                  &mb->b_mvs[0], &pmv_dontcare);  // ignore pmv                                                  &mb->b_mvs[0], &pmv_dontcare);  // ignore pmv
2391    
2392                          // interpolate search (simple, but effective)                          // interpolate search (simple, but effective)
# Line 2069  Line 2406 
2406                          if (f_sad16 < b_sad16)                          if (f_sad16 < b_sad16)
2407                          {                          {
2408                                  best_sad = f_sad16;                                  best_sad = f_sad16;
2409                                  mb->mode = MB_FORWARD;                                  mb->mode = MODE_FORWARD;
2410                          }                          }
2411                          else                          else
2412                          {                          {
2413                                  best_sad = b_sad16;                                  best_sad = b_sad16;
2414                                  mb->mode = MB_BACKWARD;                                  mb->mode = MODE_BACKWARD;
2415                          }                          }
2416    
2417                          if (i_sad16 < best_sad)                          if (i_sad16 < best_sad)
2418                          {                          {
2419                                  best_sad = i_sad16;                                  best_sad = i_sad16;
2420                                  mb->mode = MB_INTERPOLATE;                                  mb->mode = MODE_INTERPOLATE;
2421                          }                          }
2422    
2423                          if (d_sad16 < best_sad)                          if (d_sad16 < best_sad)
2424                          {                          {
2425                                  best_sad = d_sad16;                                  best_sad = d_sad16;
2426                                  mb->mode = MB_DIRECT;                                  mb->mode = MODE_DIRECT;
2427                          }                          }
2428    
2429                  }                  }
2430          }          }
2431  }  }
   
 */  

Legend:
Removed from v.136  
changed lines
  Added in v.184

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