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

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

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

revision 248, Fri Jun 28 15:14:40 2002 UTC revision 345, Sat Jul 27 23:47:01 2002 UTC
# Line 1  Line 1 
1  /**************************************************************************  /**************************************************************************
2   *   *
3     *      XVID MPEG-4 VIDEO CODEC
4     *      motion estimation
5     *
6     *      This program is an implementation of a part of one or more MPEG-4
7     *      Video tools as specified in ISO/IEC 14496-2 standard.  Those intending
8     *      to use this software module in hardware or software products are
9     *      advised that its use may infringe existing patents or copyrights, and
10     *      any such use would be at such party's own risk.  The original
11     *      developer of this software module and his/her company, and subsequent
12     *      editors and their companies, will have no liability for use of this
13     *      software or modifications or derivatives thereof.
14     *
15     *      This program is free software; you can redistribute it and/or modify
16     *      it under the terms of the GNU General Public License as published by
17     *      the Free Software Foundation; either version 2 of the License, or
18     *      (at your option) any later version.
19     *
20     *      This program is distributed in the hope that it will be useful,
21     *      but WITHOUT ANY WARRANTY; without even the implied warranty of
22     *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23     *      GNU General Public License for more details.
24     *
25     *      You should have received a copy of the GNU General Public License
26     *      along with this program; if not, write to the Free Software
27     *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28     *
29     *************************************************************************/
30    
31    /**************************************************************************
32     *
33   *  Modifications:   *  Modifications:
34   *   *
35   *      01.05.2002      updated MotionEstimationBVOP   *      01.05.2002      updated MotionEstimationBVOP
# Line 47  Line 77 
77  #include "motion.h"  #include "motion.h"
78  #include "sad.h"  #include "sad.h"
79    
 // very large value  
 #define MV_MAX_ERROR    (4096 * 256)  
   
 // stop search if sdelta < THRESHOLD  
 #define MV16_THRESHOLD  192  
 #define MV8_THRESHOLD   56  
   
 #define NEIGH_MOVE_THRESH 0  
 // how much a block's MV must differ from his neighbour  
 // to be search for INTER4V. The more, the faster...  
   
 /* sad16(0,0) bias; mpeg4 spec suggests nb/2+1 */  
 /* nb  = vop pixels * 2^(bpp-8) */  
 #define MV16_00_BIAS    (128+1)  
 #define MV8_00_BIAS     (0)  
   
 /* INTER bias for INTER/INTRA decision; mpeg4 spec suggests 2*nb */  
 #define MV16_INTER_BIAS 512  
   
 /* Parameters which control inter/inter4v decision */  
 #define IMV16X16                        5  
   
 /* vector map (vlc delta size) smoother parameters */  
 #define NEIGH_TEND_16X16        2  
 #define NEIGH_TEND_8X8          2  
   
 // fast ((A)/2)*2  
 #define EVEN(A)         (((A)<0?(A)+1:(A)) & ~1)  
   
 #define MVzero(A) ( ((A).x)==(0) && ((A).y)==(0) )  
 #define MVequal(A,B) ( ((A).x)==((B).x) && ((A).y)==((B).y) )  
   
 int32_t PMVfastSearch16(const uint8_t * const pRef,  
                                                 const uint8_t * const pRefH,  
                                                 const uint8_t * const pRefV,  
                                                 const uint8_t * const pRefHV,  
                                                 const IMAGE * const pCur,  
                                                 const int x,  
                                                 const int y,  
                                                 const uint32_t MotionFlags,  
                                                 const uint32_t iQuant,  
                                                 const uint32_t iFcode,  
                                                 const MBParam * const pParam,  
                                                 const MACROBLOCK * const pMBs,  
                                                 const MACROBLOCK * const prevMBs,  
                                                 VECTOR * const currMV,  
                                                 VECTOR * const currPMV);  
   
 int32_t EPZSSearch16(const uint8_t * const pRef,  
                                          const uint8_t * const pRefH,  
                                          const uint8_t * const pRefV,  
                                          const uint8_t * const pRefHV,  
                                          const IMAGE * const pCur,  
                                          const int x,  
                                          const int y,  
                                          const uint32_t MotionFlags,  
                                          const uint32_t iQuant,  
                                          const uint32_t iFcode,  
                                          const MBParam * const pParam,  
                                          const MACROBLOCK * const pMBs,  
                                          const MACROBLOCK * const prevMBs,  
                                          VECTOR * const currMV,  
                                          VECTOR * const currPMV);  
   
   
 int32_t PMVfastSearch8(const uint8_t * const pRef,  
                                            const uint8_t * const pRefH,  
                                            const uint8_t * const pRefV,  
                                            const uint8_t * const pRefHV,  
                                            const IMAGE * const pCur,  
                                            const int x,  
                                            const int y,  
                                            const int start_x,  
                                            const int start_y,  
                                            const uint32_t MotionFlags,  
                                            const uint32_t iQuant,  
                                            const uint32_t iFcode,  
                                            const MBParam * const pParam,  
                                            const MACROBLOCK * const pMBs,  
                                            const MACROBLOCK * const prevMBs,  
                                            VECTOR * const currMV,  
                                            VECTOR * const currPMV);  
   
 int32_t EPZSSearch8(const uint8_t * const pRef,  
                                         const uint8_t * const pRefH,  
                                         const uint8_t * const pRefV,  
                                         const uint8_t * const pRefHV,  
                                         const IMAGE * const pCur,  
                                         const int x,  
                                         const int y,  
                                         const int start_x,  
                                         const int start_y,  
                                         const uint32_t MotionFlags,  
                                         const uint32_t iQuant,  
                                         const uint32_t iFcode,  
                                         const MBParam * const pParam,  
                                         const MACROBLOCK * const pMBs,  
                                         const MACROBLOCK * const prevMBs,  
                                         VECTOR * const currMV,  
                                         VECTOR * const currPMV);  
   
   
 typedef int32_t(MainSearch16Func) (const uint8_t * const pRef,  
                                                                    const uint8_t * const pRefH,  
                                                                    const uint8_t * const pRefV,  
                                                                    const uint8_t * const pRefHV,  
                                                                    const uint8_t * const cur,  
                                                                    const int x,  
                                                                    const int y,  
                                                                    int32_t startx,  
                                                                    int32_t starty,  
                                                                    int32_t iMinSAD,  
                                                                    VECTOR * const currMV,  
                                                                    const VECTOR * const pmv,  
                                                                    const int32_t min_dx,  
                                                                    const int32_t max_dx,  
                                                                    const int32_t min_dy,  
                                                                    const int32_t max_dy,  
                                                                    const int32_t iEdgedWidth,  
                                                                    const int32_t iDiamondSize,  
                                                                    const int32_t iFcode,  
                                                                    const int32_t iQuant,  
                                                                    int iFound);  
   
 typedef MainSearch16Func *MainSearch16FuncPtr;  
80    
81    
 typedef int32_t(MainSearch8Func) (const uint8_t * const pRef,  
                                                                   const uint8_t * const pRefH,  
                                                                   const uint8_t * const pRefV,  
                                                                   const uint8_t * const pRefHV,  
                                                                   const uint8_t * const cur,  
                                                                   const int x,  
                                                                   const int y,  
                                                                   int32_t startx,  
                                                                   int32_t starty,  
                                                                   int32_t iMinSAD,  
                                                                   VECTOR * const currMV,  
                                                                   const VECTOR * const pmv,  
                                                                   const int32_t min_dx,  
                                                                   const int32_t max_dx,  
                                                                   const int32_t min_dy,  
                                                                   const int32_t max_dy,  
                                                                   const int32_t iEdgedWidth,  
                                                                   const int32_t iDiamondSize,  
                                                                   const int32_t iFcode,  
                                                                   const int32_t iQuant,  
                                                                   int iFound);  
   
 typedef MainSearch8Func *MainSearch8FuncPtr;  
   
82  static int32_t lambda_vec16[32] =       /* rounded values for lambda param for weight of motion bits as in modified H.26L */  static int32_t lambda_vec16[32] =       /* rounded values for lambda param for weight of motion bits as in modified H.26L */
83  { 0, (int) (1.00235 + 0.5), (int) (1.15582 + 0.5), (int) (1.31976 + 0.5),  { 0, (int) (1.00235 + 0.5), (int) (1.15582 + 0.5), (int) (1.31976 + 0.5),
84                  (int) (1.49591 + 0.5), (int) (1.68601 + 0.5),                  (int) (1.49591 + 0.5), (int) (1.68601 + 0.5),
# Line 274  Line 155 
155                                                                                                     mv_bits(dy, iFcode));                                                                                                     mv_bits(dy, iFcode));
156  }  }
157    
   
   
   
   
 #ifndef SEARCH16  
 #define SEARCH16        PMVfastSearch16  
 //#define SEARCH16  FullSearch16  
 //#define SEARCH16  EPZSSearch16  
 #endif  
   
 #ifndef SEARCH8  
 #define SEARCH8         PMVfastSearch8  
 //#define SEARCH8   EPZSSearch8  
 #endif  
   
158  bool  bool
159  MotionEstimation(MBParam * const pParam,  MotionEstimation(MBParam * const pParam,
160                                   FRAMEINFO * const current,                                   FRAMEINFO * const current,
# Line 305  Line 171 
171          const IMAGE *const pCurrent = &current->image;          const IMAGE *const pCurrent = &current->image;
172          const IMAGE *const pRef = &reference->image;          const IMAGE *const pRef = &reference->image;
173    
174          const VECTOR zeroMV = { 0, 0 };          static const VECTOR zeroMV = { 0, 0 };
175            VECTOR predMV;
176    
177          int32_t x, y;          int32_t x, y;
178          int32_t iIntra = 0;          int32_t iIntra = 0;
# Line 314  Line 181 
181          if (sadInit)          if (sadInit)
182                  (*sadInit) ();                  (*sadInit) ();
183    
184          for (y = 0; y < iHcount; y++)          for (y = 0; y < iHcount; y++)   {
185                  for (x = 0; x < iWcount; x++) {                  for (x = 0; x < iWcount; x++) {
186    
187                          MACROBLOCK *const pMB = &pMBs[x + y * iWcount];                          MACROBLOCK *const pMB = &pMBs[x + y * iWcount];
188    
189                            predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
190    
191                          pMB->sad16 =                          pMB->sad16 =
192                                  SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,                                  SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
193                                                   y, current->motion_flags, current->quant,                                                   x, y, predMV.x, predMV.y, predMV.x, predMV.y,
194                                                     current->motion_flags, current->quant,
195                                                   current->fcode, pParam, pMBs, prevMBs, &pMB->mv16,                                                   current->fcode, pParam, pMBs, prevMBs, &pMB->mv16,
196                                                   &pMB->pmvs[0]);                                                   &pMB->pmvs[0]);
197    
# Line 352  Line 223 
223                                           pMB->dquant == NO_CHANGE)) {                                           pMB->dquant == NO_CHANGE)) {
224                                          int32_t sad8 = IMV16X16 * current->quant;                                          int32_t sad8 = IMV16X16 * current->quant;
225    
226                                          if (sad8 < pMB->sad16)                                          if (sad8 < pMB->sad16) {
   
227                                                  sad8 += pMB->sad8[0] =                                                  sad8 += pMB->sad8[0] =
228                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
229                                                                          pCurrent, 2 * x, 2 * y, pMB->mv16.x,                                                                          pCurrent, 2 * x, 2 * y,
230                                                                          pMB->mv16.y, current->motion_flags,                                                                          pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
231                                                                            current->motion_flags,
232                                                                          current->quant, current->fcode, pParam,                                                                          current->quant, current->fcode, pParam,
233                                                                          pMBs, prevMBs, &pMB->mvs[0],                                                                          pMBs, prevMBs, &pMB->mvs[0],
234                                                                          &pMB->pmvs[0]);                                                                          &pMB->pmvs[0]);
235                                            }
236                                            if (sad8 < pMB->sad16) {
237    
238                                          if (sad8 < pMB->sad16)                                                  predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 1);
239                                                  sad8 += pMB->sad8[1] =                                                  sad8 += pMB->sad8[1] =
240                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
241                                                                          pCurrent, 2 * x + 1, 2 * y, pMB->mv16.x,                                                                          pCurrent, 2 * x + 1, 2 * y,
242                                                                          pMB->mv16.y, current->motion_flags,                                                                          pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
243                                                                            current->motion_flags,
244                                                                          current->quant, current->fcode, pParam,                                                                          current->quant, current->fcode, pParam,
245                                                                          pMBs, prevMBs, &pMB->mvs[1],                                                                          pMBs, prevMBs, &pMB->mvs[1],
246                                                                          &pMB->pmvs[1]);                                                                          &pMB->pmvs[1]);
247                                            }
248                                          if (sad8 < pMB->sad16)                                          if (sad8 < pMB->sad16) {
249                                                    predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 2);
250                                                  sad8 += pMB->sad8[2] =                                                  sad8 += pMB->sad8[2] =
251                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
252                                                                          pCurrent, 2 * x, 2 * y + 1, pMB->mv16.x,                                                                          pCurrent, 2 * x, 2 * y + 1,
253                                                                          pMB->mv16.y, current->motion_flags,                                                                          pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
254                                                                            current->motion_flags,
255                                                                          current->quant, current->fcode, pParam,                                                                          current->quant, current->fcode, pParam,
256                                                                          pMBs, prevMBs, &pMB->mvs[2],                                                                          pMBs, prevMBs, &pMB->mvs[2],
257                                                                          &pMB->pmvs[2]);                                                                          &pMB->pmvs[2]);
258                                            }
259                                          if (sad8 < pMB->sad16)                                          if (sad8 < pMB->sad16) {
260                                                    predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 3);
261                                                  sad8 += pMB->sad8[3] =                                                  sad8 += pMB->sad8[3] =
262                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
263                                                                          pCurrent, 2 * x + 1, 2 * y + 1,                                                                          pCurrent, 2 * x + 1, 2 * y + 1,
264                                                                          pMB->mv16.x, pMB->mv16.y,                                                                          pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
265                                                                          current->motion_flags, current->quant,                                                                          current->motion_flags,
266                                                                          current->fcode, pParam, pMBs, prevMBs,                                                                          current->quant, current->fcode, pParam,
267                                                                          &pMB->mvs[3], &pMB->pmvs[3]);                                                                          pMBs, prevMBs,
268                                                                            &pMB->mvs[3],
269                                                                            &pMB->pmvs[3]);
270                                            }
271    
272                                          /* decide: MODE_INTER or MODE_INTER4V                                          /* decide: MODE_INTER or MODE_INTER4V
273                                             mpeg4:   if (sad8 < pMB->sad16 - nb/2+1) use_inter4v                                             mpeg4:   if (sad8 < pMB->sad16 - nb/2+1) use_inter4v
# Line 409  Line 289 
289                          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mv16;                          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mv16;
290                          pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] =                          pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] =
291                                  pMB->sad16;                                  pMB->sad16;
   
292                  }                  }
293                            }
294    
295          return 0;          return 0;
296  }  }
297    
298    
299  #define CHECK_MV16_ZERO {\  #define CHECK_MV16_ZERO {\
300    if ( (0 <= max_dx) && (0 >= min_dx) \    if ( (0 <= max_dx) && (0 >= min_dx) \
301      && (0 <= max_dy) && (0 >= min_dy) ) \      && (0 <= max_dy) && (0 >= min_dy) ) \
302    { \    { \
303      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); \
304      iSAD += calc_delta_16(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_16(-center_x, -center_y, (uint8_t)iFcode, iQuant);\
305      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
306      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \
307  }  }
308    
309  #define NOCHECK_MV16_CANDIDATE(X,Y) { \  #define NOCHECK_MV16_CANDIDATE(X,Y) { \
310      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); \
311      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
312      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
313      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
314  }  }
# Line 436  Line 318 
318      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
319    { \    { \
320      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); \
321      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
322      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
323      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
324  }  }
# Line 446  Line 328 
328      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
329    { \    { \
330      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); \
331      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
332      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
333      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
334  }  }
# Line 456  Line 338 
338      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
339    { \    { \
340      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); \
341      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
342      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
343      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
344  }  }
# Line 464  Line 346 
346    
347  #define CHECK_MV8_ZERO {\  #define CHECK_MV8_ZERO {\
348    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); \
349    iSAD += calc_delta_8(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode, iQuant);\    iSAD += calc_delta_8(-center_x, -center_y, (uint8_t)iFcode, iQuant);\
350    if (iSAD < iMinSAD) \    if (iSAD < iMinSAD) \
351    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \
352  }  }
# Line 472  Line 354 
354  #define NOCHECK_MV8_CANDIDATE(X,Y) \  #define NOCHECK_MV8_CANDIDATE(X,Y) \
355    { \    { \
356      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); \
357      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
358      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
359      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
360  }  }
# Line 482  Line 364 
364      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
365    { \    { \
366      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); \
367      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
368      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
369      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
370  }  }
# Line 492  Line 374 
374      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
375    { \    { \
376      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); \
377      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
378      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
379      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
380  }  }
# Line 502  Line 384 
384      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
385    { \    { \
386      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); \
387      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
388      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
389      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
390  }  }
# Line 528  Line 410 
410          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
411          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
412          int32_t iSAD;          int32_t iSAD;
413          int32_t pred_x,pred_y;          VECTOR pred;
414    
415    
416          get_pmv(pMBs, x, y, pParam->mb_width, 0, &pred_x, &pred_y);          pred = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
417    
418          iSAD = sad16( cur,          iSAD = sad16( cur,
419                  get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0,0, iEdgedWidth),                  get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0,0, iEdgedWidth),
# Line 540  Line 423 
423    
424          currMV->x = 0;          currMV->x = 0;
425          currMV->y = 0;          currMV->y = 0;
426          currPMV->x = -pred_x;          currPMV->x = -pred.x;
427          currPMV->y = -pred_y;          currPMV->y = -pred.y;
428    
429          return iSAD;          return iSAD;
430    
# Line 556  Line 439 
439                                           const uint8_t * const cur,                                           const uint8_t * const cur,
440                                           const int x,                                           const int x,
441                                           const int y,                                           const int y,
442                                           int32_t startx,                                     const int start_x,
443                                           int32_t starty,                                     const int start_y,
444                                           int32_t iMinSAD,                                     int iMinSAD,
445                                           VECTOR * const currMV,                                           VECTOR * const currMV,
446                                           const VECTOR * const pmv,                                     const int center_x,
447                                       const int center_y,
448                                           const int32_t min_dx,                                           const int32_t min_dx,
449                                           const int32_t max_dx,                                           const int32_t max_dx,
450                                           const int32_t min_dy,                                           const int32_t min_dy,
# Line 574  Line 458 
458  /* Do a diamond search around given starting point, return SAD of best */  /* Do a diamond search around given starting point, return SAD of best */
459    
460          int32_t iDirection = 0;          int32_t iDirection = 0;
461            int32_t iDirectionBackup;
462          int32_t iSAD;          int32_t iSAD;
463          VECTOR backupMV;          VECTOR backupMV;
464    
465          backupMV.x = startx;          backupMV.x = start_x;
466          backupMV.y = starty;          backupMV.y = start_y;
467    
468  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
469    
# Line 587  Line 472 
472          CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);          CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);
473          CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);          CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);
474    
475          if (iDirection)          if (iDirection) {
476                  while (!iFound) {                  while (!iFound) {
477                          iFound = 1;                          iFound = 1;
478                          backupMV = *currMV;                          backupMV = *currMV;
479                            iDirectionBackup = iDirection;
480    
481                          if (iDirection != 2)                          if (iDirectionBackup != 2)
482                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
483                                                                                     backupMV.y, 1);                                                                                     backupMV.y, 1);
484                          if (iDirection != 1)                          if (iDirectionBackup != 1)
485                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
486                                                                                     backupMV.y, 2);                                                                                     backupMV.y, 2);
487                          if (iDirection != 4)                          if (iDirectionBackup != 4)
488                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
489                                                                                     backupMV.y - iDiamondSize, 3);                                                                                     backupMV.y - iDiamondSize, 3);
490                          if (iDirection != 3)                          if (iDirectionBackup != 3)
491                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
492                                                                                     backupMV.y + iDiamondSize, 4);                                                                                     backupMV.y + iDiamondSize, 4);
493                    }
494          } else {          } else {
495                  currMV->x = startx;                  currMV->x = start_x;
496                  currMV->y = starty;                  currMV->y = start_y;
497          }          }
498          return iMinSAD;          return iMinSAD;
499  }  }
# Line 619  Line 506 
506                                          const uint8_t * const cur,                                          const uint8_t * const cur,
507                                          const int x,                                          const int x,
508                                          const int y,                                          const int y,
509                                          int32_t startx,                                     const int start_x,
510                                          int32_t starty,                                     const int start_y,
511                                          int32_t iMinSAD,                                     int iMinSAD,
512                                          VECTOR * const currMV,                                          VECTOR * const currMV,
513                                          const VECTOR * const pmv,                                     const int center_x,
514                                       const int center_y,
515                                          const int32_t min_dx,                                          const int32_t min_dx,
516                                          const int32_t max_dx,                                          const int32_t max_dx,
517                                          const int32_t min_dy,                                          const int32_t min_dy,
# Line 640  Line 528 
528          int32_t iSAD;          int32_t iSAD;
529          VECTOR backupMV;          VECTOR backupMV;
530    
531          backupMV.x = startx;          backupMV.x = start_x;
532          backupMV.y = starty;          backupMV.y = start_y;
533    
534  /* It's one search with full square pattern, and new parts for all following diamonds */  /* It's one search with full square pattern, and new parts for all following diamonds */
535    
# Line 666  Line 554 
554                                                           backupMV.y + iDiamondSize, 8);                                                           backupMV.y + iDiamondSize, 8);
555    
556    
557          if (iDirection)          if (iDirection) {
558                  while (!iFound) {                  while (!iFound) {
559                          iFound = 1;                          iFound = 1;
560                          backupMV = *currMV;                          backupMV = *currMV;
# Line 675  Line 563 
563                          case 1:                          case 1:
564                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
565                                                                                     backupMV.y, 1);                                                                                     backupMV.y, 1);
566                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
567                                                                                   backupMV.y - iDiamondSize, 5);                                                                                   backupMV.y - iDiamondSize, 5);
568                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
569                                                                                   backupMV.y - iDiamondSize, 7);                                                                                   backupMV.y - iDiamondSize, 7);
570                                  break;                                  break;
571                          case 2:                          case 2:
572                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
573                                                                                   2);                                                                                   2);
574                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
575                                                                                   backupMV.y + iDiamondSize, 6);                                                                                   backupMV.y + iDiamondSize, 6);
576                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
577                                                                                   backupMV.y + iDiamondSize, 8);                                                                                   backupMV.y + iDiamondSize, 8);
578                                  break;                                  break;
579    
580                          case 3:                          case 3:
581                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
582                                                                                   4);                                                                                   4);
583                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
584                                                                                   backupMV.y - iDiamondSize, 7);                                                                                   backupMV.y - iDiamondSize, 7);
585                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
586                                                                                   backupMV.y + iDiamondSize, 8);                                                                                   backupMV.y + iDiamondSize, 8);
587                                  break;                                  break;
588    
589                          case 4:                          case 4:
590                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
591                                                                                   3);                                                                                   3);
592                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
593                                                                                   backupMV.y - iDiamondSize, 5);                                                                                   backupMV.y - iDiamondSize, 5);
594                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
595                                                                                   backupMV.y + iDiamondSize, 6);                                                                                   backupMV.y + iDiamondSize, 6);
596                                  break;                                  break;
597    
598                          case 5:                          case 5:
599                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
600                                                                                   1);                                                                                   1);
601                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
602                                                                                   3);                                                                                   3);
603                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
604                                                                                   backupMV.y - iDiamondSize, 5);                                                                                   backupMV.y - iDiamondSize, 5);
605                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
606                                                                                   backupMV.y + iDiamondSize, 6);                                                                                   backupMV.y + iDiamondSize, 6);
607                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
608                                                                                   backupMV.y - iDiamondSize, 7);                                                                                   backupMV.y - iDiamondSize, 7);
609                                  break;                                  break;
610    
611                          case 6:                          case 6:
612                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
613                                                                                   2);                                                                                   2);
614                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
615                                                                                   3);                                                                                   3);
616    
617                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
618                                                                                   backupMV.y - iDiamondSize, 5);                                                                                   backupMV.y - iDiamondSize, 5);
619                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
620                                                                                   backupMV.y + iDiamondSize, 6);                                                                                   backupMV.y + iDiamondSize, 6);
621                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
622                                                                                   backupMV.y + iDiamondSize, 8);                                                                                   backupMV.y + iDiamondSize, 8);
623    
624                                  break;                                  break;
# Line 738  Line 626 
626                          case 7:                          case 7:
627                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
628                                                                                     backupMV.y, 1);                                                                                     backupMV.y, 1);
629                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
630                                                                                   4);                                                                                   4);
631                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
632                                                                                   backupMV.y - iDiamondSize, 5);                                                                                   backupMV.y - iDiamondSize, 5);
633                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
634                                                                                   backupMV.y - iDiamondSize, 7);                                                                                   backupMV.y - iDiamondSize, 7);
635                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
636                                                                                   backupMV.y + iDiamondSize, 8);                                                                                   backupMV.y + iDiamondSize, 8);
637                                  break;                                  break;
638    
639                          case 8:                          case 8:
640                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
641                                                                                   2);                                                                                   2);
642                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
643                                                                                   4);                                                                                   4);
644                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
645                                                                                   backupMV.y + iDiamondSize, 6);                                                                                   backupMV.y + iDiamondSize, 6);
646                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
647                                                                                   backupMV.y - iDiamondSize, 7);                                                                                   backupMV.y - iDiamondSize, 7);
648                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
649                                                                                   backupMV.y + iDiamondSize, 8);                                                                                   backupMV.y + iDiamondSize, 8);
650                                  break;                                  break;
651                          default:                          default:
652                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
653                                                                                   1);                                                                                   1);
654                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
655                                                                                   2);                                                                                   2);
656                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
657                                                                                   3);                                                                                   3);
658                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
659                                                                                   4);                                                                                   4);
660    
661                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
662                                                                                   backupMV.y - iDiamondSize, 5);                                                                                   backupMV.y - iDiamondSize, 5);
663                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
664                                                                                   backupMV.y + iDiamondSize, 6);                                                                                   backupMV.y + iDiamondSize, 6);
665                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
666                                                                                   backupMV.y - iDiamondSize, 7);                                                                                   backupMV.y - iDiamondSize, 7);
667                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
668                                                                                   backupMV.y + iDiamondSize, 8);                                                                                   backupMV.y + iDiamondSize, 8);
669                                  break;                                  break;
670                          }                          }
671                    }
672          } else {          } else {
673                  currMV->x = startx;                  currMV->x = start_x;
674                  currMV->y = starty;                  currMV->y = start_y;
675          }          }
676          return iMinSAD;          return iMinSAD;
677  }  }
# Line 796  Line 685 
685                                    const uint8_t * const cur,                                    const uint8_t * const cur,
686                                    const int x,                                    const int x,
687                                    const int y,                                    const int y,
688                                    int32_t startx,                                     const int start_x,
689                                    int32_t starty,                                     const int start_y,
690                                    int32_t iMinSAD,                                     int iMinSAD,
691                                    VECTOR * const currMV,                                    VECTOR * const currMV,
692                                    const VECTOR * const pmv,                                     const int center_x,
693                                       const int center_y,
694                                    const int32_t min_dx,                                    const int32_t min_dx,
695                                    const int32_t max_dx,                                    const int32_t max_dx,
696                                    const int32_t min_dy,                                    const int32_t min_dy,
# Line 815  Line 705 
705          int32_t dx, dy;          int32_t dx, dy;
706          VECTOR backupMV;          VECTOR backupMV;
707    
708          backupMV.x = startx;          backupMV.x = start_x;
709          backupMV.y = starty;          backupMV.y = start_y;
710    
711          for (dx = min_dx; dx <= max_dx; dx += iDiamondSize)          for (dx = min_dx; dx <= max_dx; dx += iDiamondSize)
712                  for (dy = min_dy; dy <= max_dy; dy += iDiamondSize)                  for (dy = min_dy; dy <= max_dy; dy += iDiamondSize)
# Line 833  Line 723 
723                                                  const uint8_t * const cur,                                                  const uint8_t * const cur,
724                                                  const int x,                                                  const int x,
725                                                  const int y,                                                  const int y,
726                                                  int32_t startx,                                             int start_x,
727                                                  int32_t starty,                                             int start_y,
728                                                  int32_t iMinSAD,                                             int iMinSAD,
729                                                  VECTOR * const currMV,                                                  VECTOR * const currMV,
730                                                  const VECTOR * const pmv,                                             const int center_x,
731                                               const int center_y,
732                                                  const int32_t min_dx,                                                  const int32_t min_dx,
733                                                  const int32_t max_dx,                                                  const int32_t max_dx,
734                                                  const int32_t min_dy,                                                  const int32_t min_dy,
# Line 854  Line 745 
745  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
746    
747          if (iDirection) {          if (iDirection) {
748                  CHECK_MV16_CANDIDATE(startx - iDiamondSize, starty);                  CHECK_MV16_CANDIDATE(start_x - iDiamondSize, start_y);
749                  CHECK_MV16_CANDIDATE(startx + iDiamondSize, starty);                  CHECK_MV16_CANDIDATE(start_x + iDiamondSize, start_y);
750                  CHECK_MV16_CANDIDATE(startx, starty - iDiamondSize);                  CHECK_MV16_CANDIDATE(start_x, start_y - iDiamondSize);
751                  CHECK_MV16_CANDIDATE(startx, starty + iDiamondSize);                  CHECK_MV16_CANDIDATE(start_x, start_y + iDiamondSize);
752          } else {          } else {
753                  int bDirection = 1 + 2 + 4 + 8;                  int bDirection = 1 + 2 + 4 + 8;
754    
755                  do {                  do {
756                          iDirection = 0;                          iDirection = 0;
757                          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)                          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)
758                                  CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize, starty, 1);                                  CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
759    
760                          if (bDirection & 2)                          if (bDirection & 2)
761                                  CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize, starty, 2);                                  CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
762    
763                          if (bDirection & 4)                          if (bDirection & 4)
764                                  CHECK_MV16_CANDIDATE_DIR(startx, starty - iDiamondSize, 4);                                  CHECK_MV16_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
765    
766                          if (bDirection & 8)                          if (bDirection & 8)
767                                  CHECK_MV16_CANDIDATE_DIR(startx, starty + iDiamondSize, 8);                                  CHECK_MV16_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
768    
769                          /* now we're doing diagonal checks near our candidate */                          /* now we're doing diagonal checks near our candidate */
770    
# Line 881  Line 772 
772                          {                          {
773                                  bDirection = iDirection;                                  bDirection = iDirection;
774                                  iDirection = 0;                                  iDirection = 0;
775                                  startx = currMV->x;                                  start_x = currMV->x;
776                                  starty = currMV->y;                                  start_y = currMV->y;
777                                  if (bDirection & 3)     //our candidate is left or right                                  if (bDirection & 3)     //our candidate is left or right
778                                  {                                  {
779                                          CHECK_MV16_CANDIDATE_DIR(startx, starty + iDiamondSize, 8);                                          CHECK_MV16_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
780                                          CHECK_MV16_CANDIDATE_DIR(startx, starty - iDiamondSize, 4);                                          CHECK_MV16_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
781                                  } else                  // what remains here is up or down                                  } else                  // what remains here is up or down
782                                  {                                  {
783                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize, starty, 2);                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
784                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize, starty, 1);                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
785                                  }                                  }
786    
787                                  if (iDirection) {                                  if (iDirection) {
788                                          bDirection += iDirection;                                          bDirection += iDirection;
789                                          startx = currMV->x;                                          start_x = currMV->x;
790                                          starty = currMV->y;                                          start_y = currMV->y;
791                                  }                                  }
792                          } else                          //about to quit, eh? not so fast....                          } else                          //about to quit, eh? not so fast....
793                          {                          {
794                                  switch (bDirection) {                                  switch (bDirection) {
795                                  case 2:                                  case 2:
796                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
797                                                                                           starty - iDiamondSize, 2 + 4);                                                                                           start_y - iDiamondSize, 2 + 4);
798                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
799                                                                                           starty + iDiamondSize, 2 + 8);                                                                                           start_y + iDiamondSize, 2 + 8);
800                                          break;                                          break;
801                                  case 1:                                  case 1:
802                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,  
803                                                                                           starty - iDiamondSize, 1 + 4);                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
804                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,                                                                                           start_y - iDiamondSize, 1 + 4);
805                                                                                           starty + iDiamondSize, 1 + 8);                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
806                                                                                             start_y + iDiamondSize, 1 + 8);
807                                          break;                                          break;
808                                  case 2 + 4:                                  case 2 + 4:
809                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
810                                                                                           starty - iDiamondSize, 1 + 4);                                                                                           start_y - iDiamondSize, 1 + 4);
811                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
812                                                                                           starty - iDiamondSize, 2 + 4);                                                                                           start_y - iDiamondSize, 2 + 4);
813                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
814                                                                                           starty + iDiamondSize, 2 + 8);                                                                                           start_y + iDiamondSize, 2 + 8);
815                                          break;                                          break;
816                                  case 4:                                  case 4:
817                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
818                                                                                           starty - iDiamondSize, 2 + 4);                                                                                           start_y - iDiamondSize, 2 + 4);
819                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
820                                                                                           starty - iDiamondSize, 1 + 4);                                                                                           start_y - iDiamondSize, 1 + 4);
821                                          break;                                          break;
822                                  case 8:                                  case 8:
823                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
824                                                                                           starty + iDiamondSize, 2 + 8);                                                                                           start_y + iDiamondSize, 2 + 8);
825                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
826                                                                                           starty + iDiamondSize, 1 + 8);                                                                                           start_y + iDiamondSize, 1 + 8);
827                                          break;                                          break;
828                                  case 1 + 4:                                  case 1 + 4:
829                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
830                                                                                           starty + iDiamondSize, 1 + 8);                                                                                           start_y + iDiamondSize, 1 + 8);
831                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
832                                                                                           starty - iDiamondSize, 1 + 4);                                                                                           start_y - iDiamondSize, 1 + 4);
833                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
834                                                                                           starty - iDiamondSize, 2 + 4);                                                                                           start_y - iDiamondSize, 2 + 4);
835                                          break;                                          break;
836                                  case 2 + 8:                                  case 2 + 8:
837                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
838                                                                                           starty - iDiamondSize, 1 + 4);                                                                                           start_y - iDiamondSize, 1 + 4);
839                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
840                                                                                           starty + iDiamondSize, 1 + 8);                                                                                           start_y + iDiamondSize, 1 + 8);
841                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
842                                                                                           starty + iDiamondSize, 2 + 8);                                                                                           start_y + iDiamondSize, 2 + 8);
843                                          break;                                          break;
844                                  case 1 + 8:                                  case 1 + 8:
845                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
846                                                                                           starty - iDiamondSize, 2 + 4);                                                                                           start_y - iDiamondSize, 2 + 4);
847                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
848                                                                                           starty + iDiamondSize, 2 + 8);                                                                                           start_y + iDiamondSize, 2 + 8);
849                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
850                                                                                           starty + iDiamondSize, 1 + 8);                                                                                           start_y + iDiamondSize, 1 + 8);
851                                          break;                                          break;
852                                  default:                //1+2+4+8 == we didn't find anything at all                                  default:                //1+2+4+8 == we didn't find anything at all
853                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
854                                                                                           starty - iDiamondSize, 1 + 4);                                                                                           start_y - iDiamondSize, 1 + 4);
855                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
856                                                                                           starty + iDiamondSize, 1 + 8);                                                                                           start_y + iDiamondSize, 1 + 8);
857                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
858                                                                                           starty - iDiamondSize, 2 + 4);                                                                                           start_y - iDiamondSize, 2 + 4);
859                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
860                                                                                           starty + iDiamondSize, 2 + 8);                                                                                           start_y + iDiamondSize, 2 + 8);
861                                          break;                                          break;
862                                  }                                  }
863                                  if (!iDirection)                                  if (!iDirection)
864                                          break;          //ok, the end. really                                          break;          //ok, the end. really
865                                  else {                                  else {
866                                          bDirection = iDirection;                                          bDirection = iDirection;
867                                          startx = currMV->x;                                          start_x = currMV->x;
868                                          starty = currMV->y;                                          start_y = currMV->y;
869                                  }                                  }
870                          }                          }
871                  }                  }
# Line 982  Line 874 
874          return iMinSAD;          return iMinSAD;
875  }  }
876    
 int32_t  
 AdvDiamond8_MainSearch(const uint8_t * const pRef,  
                                            const uint8_t * const pRefH,  
                                            const uint8_t * const pRefV,  
                                            const uint8_t * const pRefHV,  
                                            const uint8_t * const cur,  
                                            const int x,  
                                            const int y,  
                                            int32_t startx,  
                                            int32_t starty,  
                                            int32_t iMinSAD,  
                                            VECTOR * const currMV,  
                                            const VECTOR * const pmv,  
                                            const int32_t min_dx,  
                                            const int32_t max_dx,  
                                            const int32_t min_dy,  
                                            const int32_t max_dy,  
                                            const int32_t iEdgedWidth,  
                                            const int32_t iDiamondSize,  
                                            const int32_t iFcode,  
                                            const int32_t iQuant,  
                                            int iDirection)  
 {  
   
         int32_t iSAD;  
877    
878  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */  #define CHECK_MV16_F_INTERPOL(X,Y,BX,BY) { \
879      if ( ((X) <= max_dx) && ((X) >= min_dx) \
880        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
881      { \
882        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
883        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
884        if (iSAD < iMinSAD) \
885        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
886    }
887    
888          if (iDirection) {  #define CHECK_MV16_F_INTERPOL_DIR(X,Y,BX,BY,D) { \
889                  CHECK_MV8_CANDIDATE(startx - iDiamondSize, starty);    if ( ((X) <= max_dx) && ((X) >= min_dx) \
890                  CHECK_MV8_CANDIDATE(startx + iDiamondSize, starty);      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
891                  CHECK_MV8_CANDIDATE(startx, starty - iDiamondSize);    { \
892                  CHECK_MV8_CANDIDATE(startx, starty + iDiamondSize);      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
893          } else {      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
894                  int bDirection = 1 + 2 + 4 + 8;      if (iSAD < iMinSAD) \
895        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
896    }
897    
898                  do {  #define CHECK_MV16_F_INTERPOL_FOUND(X,Y,BX,BY,D) { \
899                          iDirection = 0;    if ( ((X) <= max_dx) && ((X) >= min_dx) \
900                          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)      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
901                                  CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize, starty, 1);    { \
902        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
903        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
904        if (iSAD < iMinSAD) \
905        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
906    }
907    
908    
909    #define CHECK_MV16_B_INTERPOL(FX,FY,X,Y) { \
910      if ( ((X) <= max_dx) && ((X) >= min_dx) \
911        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
912      { \
913        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
914        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
915        if (iSAD < iMinSAD) \
916        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
917    }
918    
919    
920    #define CHECK_MV16_B_INTERPOL_DIR(FX,FY,X,Y,D) { \
921      if ( ((X) <= max_dx) && ((X) >= min_dx) \
922        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
923      { \
924        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
925        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
926        if (iSAD < iMinSAD) \
927        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
928    }
929    
930    
931    #define CHECK_MV16_B_INTERPOL_FOUND(FX,FY,X,Y,D) { \
932      if ( ((X) <= max_dx) && ((X) >= min_dx) \
933        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
934      { \
935        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
936        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
937        if (iSAD < iMinSAD) \
938        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
939    }
940    
941    
942    #if (0==1)
943    int32_t
944    Diamond16_InterpolMainSearch(
945                                            const uint8_t * const f_pRef,
946                                             const uint8_t * const f_pRefH,
947                                             const uint8_t * const f_pRefV,
948                                             const uint8_t * const f_pRefHV,
949                                             const uint8_t * const cur,
950    
951                                            const uint8_t * const b_pRef,
952                                             const uint8_t * const b_pRefH,
953                                             const uint8_t * const b_pRefV,
954                                             const uint8_t * const b_pRefHV,
955    
956                                             const int x,
957                                             const int y,
958    
959                                       const int f_start_x,
960                                       const int f_start_y,
961                                       const int b_start_x,
962                                       const int b_start_y,
963    
964                                       int iMinSAD,
965                                       VECTOR * const f_currMV,
966                                       VECTOR * const b_currMV,
967    
968                                       const int f_center_x,
969                                       const int f_center_y,
970                                       const int b_center_x,
971                                       const int b_center_y,
972    
973                                             const int32_t min_dx,
974                                             const int32_t max_dx,
975                                             const int32_t min_dy,
976                                             const int32_t max_dy,
977                                             const int32_t iEdgedWidth,
978                                             const int32_t iDiamondSize,
979    
980                                             const int32_t f_iFcode,
981                                             const int32_t b_iFcode,
982    
983                                             const int32_t iQuant,
984                                             int iFound)
985    {
986    /* Do a diamond search around given starting point, return SAD of best */
987    
988            int32_t f_iDirection = 0;
989            int32_t b_iDirection = 0;
990            int32_t iSAD;
991    
992            VECTOR f_backupMV;
993            VECTOR b_backupMV;
994    
995            f_backupMV.x = start_x;
996            f_backupMV.y = start_y;
997            b_backupMV.x = start_x;
998            b_backupMV.y = start_y;
999    
1000    /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
1001    
1002            CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y, 1);
1003            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y, 2);
1004            CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);
1005            CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);
1006    
1007            if (iDirection)
1008                    while (!iFound) {
1009                            iFound = 1;
1010                            backupMV = *currMV;
1011    
1012                            if (iDirection != 2)
1013                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1014                                                                                       backupMV.y, 1);
1015                            if (iDirection != 1)
1016                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1017                                                                                       backupMV.y, 2);
1018                            if (iDirection != 4)
1019                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
1020                                                                                       backupMV.y - iDiamondSize, 3);
1021                            if (iDirection != 3)
1022                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
1023                                                                                       backupMV.y + iDiamondSize, 4);
1024            } else {
1025                    currMV->x = start_x;
1026                    currMV->y = start_y;
1027            }
1028            return iMinSAD;
1029    }
1030    #endif
1031    
1032    
1033    int32_t
1034    AdvDiamond8_MainSearch(const uint8_t * const pRef,
1035                                               const uint8_t * const pRefH,
1036                                               const uint8_t * const pRefV,
1037                                               const uint8_t * const pRefHV,
1038                                               const uint8_t * const cur,
1039                                               const int x,
1040                                               const int y,
1041                                               int start_x,
1042                                               int start_y,
1043                                               int iMinSAD,
1044                                               VECTOR * const currMV,
1045                                               const int center_x,
1046                                               const int center_y,
1047                                               const int32_t min_dx,
1048                                               const int32_t max_dx,
1049                                               const int32_t min_dy,
1050                                               const int32_t max_dy,
1051                                               const int32_t iEdgedWidth,
1052                                               const int32_t iDiamondSize,
1053                                               const int32_t iFcode,
1054                                               const int32_t iQuant,
1055                                               int iDirection)
1056    {
1057    
1058            int32_t iSAD;
1059    
1060    /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
1061    
1062            if (iDirection) {
1063                    CHECK_MV8_CANDIDATE(start_x - iDiamondSize, start_y);
1064                    CHECK_MV8_CANDIDATE(start_x + iDiamondSize, start_y);
1065                    CHECK_MV8_CANDIDATE(start_x, start_y - iDiamondSize);
1066                    CHECK_MV8_CANDIDATE(start_x, start_y + iDiamondSize);
1067            } else {
1068                    int bDirection = 1 + 2 + 4 + 8;
1069    
1070                    do {
1071                            iDirection = 0;
1072                            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)
1073                                    CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
1074    
1075                          if (bDirection & 2)                          if (bDirection & 2)
1076                                  CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize, starty, 2);                                  CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
1077    
1078                          if (bDirection & 4)                          if (bDirection & 4)
1079                                  CHECK_MV8_CANDIDATE_DIR(startx, starty - iDiamondSize, 4);                                  CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
1080    
1081                          if (bDirection & 8)                          if (bDirection & 8)
1082                                  CHECK_MV8_CANDIDATE_DIR(startx, starty + iDiamondSize, 8);                                  CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
1083    
1084                          /* now we're doing diagonal checks near our candidate */                          /* now we're doing diagonal checks near our candidate */
1085    
# Line 1038  Line 1087 
1087                          {                          {
1088                                  bDirection = iDirection;                                  bDirection = iDirection;
1089                                  iDirection = 0;                                  iDirection = 0;
1090                                  startx = currMV->x;                                  start_x = currMV->x;
1091                                  starty = currMV->y;                                  start_y = currMV->y;
1092                                  if (bDirection & 3)     //our candidate is left or right                                  if (bDirection & 3)     //our candidate is left or right
1093                                  {                                  {
1094                                          CHECK_MV8_CANDIDATE_DIR(startx, starty + iDiamondSize, 8);                                          CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
1095                                          CHECK_MV8_CANDIDATE_DIR(startx, starty - iDiamondSize, 4);                                          CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
1096                                  } else                  // what remains here is up or down                                  } else                  // what remains here is up or down
1097                                  {                                  {
1098                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize, starty, 2);                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
1099                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize, starty, 1);                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
1100                                  }                                  }
1101    
1102                                  if (iDirection) {                                  if (iDirection) {
1103                                          bDirection += iDirection;                                          bDirection += iDirection;
1104                                          startx = currMV->x;                                          start_x = currMV->x;
1105                                          starty = currMV->y;                                          start_y = currMV->y;
1106                                  }                                  }
1107                          } else                          //about to quit, eh? not so fast....                          } else                          //about to quit, eh? not so fast....
1108                          {                          {
1109                                  switch (bDirection) {                                  switch (bDirection) {
1110                                  case 2:                                  case 2:
1111                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1112                                                                                          starty - iDiamondSize, 2 + 4);                                                                                          start_y - iDiamondSize, 2 + 4);
1113                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1114                                                                                          starty + iDiamondSize, 2 + 8);                                                                                          start_y + iDiamondSize, 2 + 8);
1115                                          break;                                          break;
1116                                  case 1:                                  case 1:
1117                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1118                                                                                          starty - iDiamondSize, 1 + 4);                                                                                          start_y - iDiamondSize, 1 + 4);
1119                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1120                                                                                          starty + iDiamondSize, 1 + 8);                                                                                          start_y + iDiamondSize, 1 + 8);
1121                                          break;                                          break;
1122                                  case 2 + 4:                                  case 2 + 4:
1123                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1124                                                                                          starty - iDiamondSize, 1 + 4);                                                                                          start_y - iDiamondSize, 1 + 4);
1125                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1126                                                                                          starty - iDiamondSize, 2 + 4);                                                                                          start_y - iDiamondSize, 2 + 4);
1127                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1128                                                                                          starty + iDiamondSize, 2 + 8);                                                                                          start_y + iDiamondSize, 2 + 8);
1129                                          break;                                          break;
1130                                  case 4:                                  case 4:
1131                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1132                                                                                          starty - iDiamondSize, 2 + 4);                                                                                          start_y - iDiamondSize, 2 + 4);
1133                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1134                                                                                          starty - iDiamondSize, 1 + 4);                                                                                          start_y - iDiamondSize, 1 + 4);
1135                                          break;                                          break;
1136                                  case 8:                                  case 8:
1137                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1138                                                                                          starty + iDiamondSize, 2 + 8);                                                                                          start_y + iDiamondSize, 2 + 8);
1139                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1140                                                                                          starty + iDiamondSize, 1 + 8);                                                                                          start_y + iDiamondSize, 1 + 8);
1141                                          break;                                          break;
1142                                  case 1 + 4:                                  case 1 + 4:
1143                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1144                                                                                          starty + iDiamondSize, 1 + 8);                                                                                          start_y + iDiamondSize, 1 + 8);
1145                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1146                                                                                          starty - iDiamondSize, 1 + 4);                                                                                          start_y - iDiamondSize, 1 + 4);
1147                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1148                                                                                          starty - iDiamondSize, 2 + 4);                                                                                          start_y - iDiamondSize, 2 + 4);
1149                                          break;                                          break;
1150                                  case 2 + 8:                                  case 2 + 8:
1151                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1152                                                                                          starty - iDiamondSize, 1 + 4);                                                                                          start_y - iDiamondSize, 1 + 4);
1153                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1154                                                                                          starty + iDiamondSize, 1 + 8);                                                                                          start_y + iDiamondSize, 1 + 8);
1155                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1156                                                                                          starty + iDiamondSize, 2 + 8);                                                                                          start_y + iDiamondSize, 2 + 8);
1157                                          break;                                          break;
1158                                  case 1 + 8:                                  case 1 + 8:
1159                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1160                                                                                          starty - iDiamondSize, 2 + 4);                                                                                          start_y - iDiamondSize, 2 + 4);
1161                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1162                                                                                          starty + iDiamondSize, 2 + 8);                                                                                          start_y + iDiamondSize, 2 + 8);
1163                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1164                                                                                          starty + iDiamondSize, 1 + 8);                                                                                          start_y + iDiamondSize, 1 + 8);
1165                                          break;                                          break;
1166                                  default:                //1+2+4+8 == we didn't find anything at all                                  default:                //1+2+4+8 == we didn't find anything at all
1167                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1168                                                                                          starty - iDiamondSize, 1 + 4);                                                                                          start_y - iDiamondSize, 1 + 4);
1169                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1170                                                                                          starty + iDiamondSize, 1 + 8);                                                                                          start_y + iDiamondSize, 1 + 8);
1171                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1172                                                                                          starty - iDiamondSize, 2 + 4);                                                                                          start_y - iDiamondSize, 2 + 4);
1173                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1174                                                                                          starty + iDiamondSize, 2 + 8);                                                                                          start_y + iDiamondSize, 2 + 8);
1175                                          break;                                          break;
1176                                  }                                  }
1177                                  if (!(iDirection))                                  if (!(iDirection))
1178                                          break;          //ok, the end. really                                          break;          //ok, the end. really
1179                                  else {                                  else {
1180                                          bDirection = iDirection;                                          bDirection = iDirection;
1181                                          startx = currMV->x;                                          start_x = currMV->x;
1182                                          starty = currMV->y;                                          start_y = currMV->y;
1183                                  }                                  }
1184                          }                          }
1185                  }                  }
# Line 1148  Line 1197 
1197                                   const uint8_t * const cur,                                   const uint8_t * const cur,
1198                                   const int x,                                   const int x,
1199                                   const int y,                                   const int y,
1200                                   int32_t startx,                             const int start_x,
1201                                   int32_t starty,                             const int start_y,
1202                                   int32_t iMinSAD,                             int iMinSAD,
1203                                   VECTOR * const currMV,                                   VECTOR * const currMV,
1204                                   const VECTOR * const pmv,                             const int center_x,
1205                               const int center_y,
1206                                   const int32_t min_dx,                                   const int32_t min_dx,
1207                                   const int32_t max_dx,                                   const int32_t max_dx,
1208                                   const int32_t min_dy,                                   const int32_t min_dy,
# Line 1167  Line 1217 
1217          int32_t dx, dy;          int32_t dx, dy;
1218          VECTOR backupMV;          VECTOR backupMV;
1219    
1220          backupMV.x = startx;          backupMV.x = start_x;
1221          backupMV.y = starty;          backupMV.y = start_y;
1222    
1223          for (dx = min_dx; dx <= max_dx; dx += iDiamondSize)          for (dx = min_dx; dx <= max_dx; dx += iDiamondSize)
1224                  for (dy = min_dy; dy <= max_dy; dy += iDiamondSize)                  for (dy = min_dy; dy <= max_dy; dy += iDiamondSize)
# Line 1177  Line 1227 
1227          return iMinSAD;          return iMinSAD;
1228  }  }
1229    
1230    Halfpel8_RefineFuncPtr Halfpel8_Refine;
1231    
1232  int32_t  int32_t
1233  Halfpel16_Refine(const uint8_t * const pRef,  Halfpel16_Refine(const uint8_t * const pRef,
# Line 1189  Line 1239 
1239                                   const int y,                                   const int y,
1240                                   VECTOR * const currMV,                                   VECTOR * const currMV,
1241                                   int32_t iMinSAD,                                   int32_t iMinSAD,
1242                                   const VECTOR * const pmv,                             const int center_x,
1243                               const int center_y,
1244                                   const int32_t min_dx,                                   const int32_t min_dx,
1245                                   const int32_t max_dx,                                   const int32_t max_dx,
1246                                   const int32_t min_dy,                                   const int32_t min_dy,
# Line 1218  Line 1269 
1269  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
1270    
1271    
1272    
1273  int32_t  int32_t
1274  PMVfastSearch16(const uint8_t * const pRef,  PMVfastSearch16(const uint8_t * const pRef,
1275                                  const uint8_t * const pRefH,                                  const uint8_t * const pRefH,
# Line 1226  Line 1278 
1278                                  const IMAGE * const pCur,                                  const IMAGE * const pCur,
1279                                  const int x,                                  const int x,
1280                                  const int y,                                  const int y,
1281                                    const int start_x,
1282                                    const int start_y,
1283                                    const int center_x,
1284                                    const int center_y,
1285                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
1286                                  const uint32_t iQuant,                                  const uint32_t iQuant,
1287                                  const uint32_t iFcode,                                  const uint32_t iFcode,
# Line 1259  Line 1315 
1315    
1316          MainSearch16FuncPtr MainSearchPtr;          MainSearch16FuncPtr MainSearchPtr;
1317    
 //  const MACROBLOCK * const pMB = pMBs + x + y * iWcount;  
1318          const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;          const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
1319    
1320          static int32_t threshA, threshB;          int32_t threshA, threshB;
1321          int32_t bPredEq;          int32_t bPredEq;
1322          int32_t iMinSAD, iSAD;          int32_t iMinSAD, iSAD;
1323    
# Line 1280  Line 1335 
1335          }          }
1336    
1337          /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1338          bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad, 0, 0);          //bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
1339            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
1340    
1341          if ((x == 0) && (y == 0)) {          if ((x == 0) && (y == 0)) {
1342                  threshA = 512;                  threshA = 512;
1343                  threshB = 1024;                  threshB = 1024;
   
1344          } else {          } else {
1345                  threshA = psad[0];                  threshA = psad[0];
1346                  threshB = threshA + 256;                  threshB = threshA + 256;
# Line 1306  Line 1361 
1361     If SAD<=256 goto Step 10.     If SAD<=256 goto Step 10.
1362  */  */
1363    
1364          *currMV = pmv[0];                       /* current best := prediction */          currMV->x = start_x;
1365            currMV->y = start_y;
1366    
1367          if (!(MotionFlags & PMV_HALFPEL16)) {   /* This should NOT be necessary! */          if (!(MotionFlags & PMV_HALFPEL16)) {   /* This should NOT be necessary! */
1368                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
1369                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
# Line 1330  Line 1387 
1387                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
1388                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
1389          iMinSAD +=          iMinSAD +=
1390                  calc_delta_16(currMV->x - pmv[0].x, currMV->y - pmv[0].y,                  calc_delta_16(currMV->x - center_x, currMV->y - center_y,
1391                                            (uint8_t) iFcode, iQuant);                                            (uint8_t) iFcode, iQuant);
1392    
1393          if ((iMinSAD < 256) ||          if ((iMinSAD < 256) ||
1394                  ((MVequal(*currMV, prevMB->mvs[0])) &&                  ((MVequal(*currMV, prevMB->mvs[0])) &&
1395                   ((uint32_t) iMinSAD < prevMB->sad16))) {                   ((int32_t) iMinSAD < prevMB->sad16))) {
1396                  if (iMinSAD < 2 * iQuant)       // high chances for SKIP-mode                  if (iMinSAD < 2 * iQuant)       // high chances for SKIP-mode
1397                  {                  {
1398                          if (!MVzero(*currMV)) {                          if (!MVzero(*currMV)) {
# Line 1439  Line 1496 
1496    
1497          if ((iMinSAD <= threshA) ||          if ((iMinSAD <= threshA) ||
1498                  (MVequal(*currMV, prevMB->mvs[0]) &&                  (MVequal(*currMV, prevMB->mvs[0]) &&
1499                   ((uint32_t) iMinSAD < prevMB->sad16))) {                   ((int32_t) iMinSAD < prevMB->sad16))) {
1500                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1501                          goto PMVfast16_Terminate_without_Refine;                          goto PMVfast16_Terminate_without_Refine;
1502                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1466  Line 1523 
1523    
1524          backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
1525    
1526    
1527  /* 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 */
1528          iSAD =          iSAD =
1529                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1530                                                    currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx,                                                    currMV->x, currMV->y, iMinSAD, &newMV, center_x, center_y,
1531                                                      min_dx, max_dx,
1532                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
1533                                                    iQuant, iFound);                                                    iQuant, iFound);
1534    
# Line 1484  Line 1543 
1543                  if (!(MVequal(pmv[0], backupMV))) {                  if (!(MVequal(pmv[0], backupMV))) {
1544                          iSAD =                          iSAD =
1545                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1546                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, pmv,                                                                    center_x, center_y, iMinSAD, &newMV, center_x, center_y,
1547                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1548                                                                    iDiamondSize, iFcode, iQuant, iFound);                                                                    iDiamondSize, iFcode, iQuant, iFound);
1549    
# Line 1497  Line 1556 
1556                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
1557                          iSAD =                          iSAD =
1558                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
1559                                                                    iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy,                                                                    iMinSAD, &newMV, center_x, center_y,
1560                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,                                                                    min_dx, max_dx, min_dy, max_dy,
1561                                                                      iEdgedWidth, iDiamondSize, iFcode,
1562                                                                    iQuant, iFound);                                                                    iQuant, iFound);
1563    
1564                          if (iSAD < iMinSAD) {                          if (iSAD < iMinSAD) {
# Line 1516  Line 1576 
1576          if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step
1577                  iMinSAD =                  iMinSAD =
1578                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
1579                                                           iMinSAD, pmv, min_dx, max_dx, min_dy, max_dy,                                                           iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
1580                                                           iFcode, iQuant, iEdgedWidth);                                                           iFcode, iQuant, iEdgedWidth);
1581    
1582    PMVfast16_Terminate_without_Refine:    PMVfast16_Terminate_without_Refine:
1583          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
1584          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
1585          return iMinSAD;          return iMinSAD;
1586  }  }
1587    
# Line 1538  Line 1598 
1598                                          const uint8_t * const cur,                                          const uint8_t * const cur,
1599                                          const int x,                                          const int x,
1600                                          const int y,                                          const int y,
1601                                          int32_t startx,                                          int32_t start_x,
1602                                          int32_t starty,                                          int32_t start_y,
1603                                          int32_t iMinSAD,                                          int32_t iMinSAD,
1604                                          VECTOR * const currMV,                                          VECTOR * const currMV,
1605                                          const VECTOR * const pmv,                                     const int center_x,
1606                                       const int center_y,
1607                                          const int32_t min_dx,                                          const int32_t min_dx,
1608                                          const int32_t max_dx,                                          const int32_t max_dx,
1609                                          const int32_t min_dy,                                          const int32_t min_dy,
# Line 1556  Line 1617 
1617  /* Do a diamond search around given starting point, return SAD of best */  /* Do a diamond search around given starting point, return SAD of best */
1618    
1619          int32_t iDirection = 0;          int32_t iDirection = 0;
1620            int32_t iDirectionBackup;
1621          int32_t iSAD;          int32_t iSAD;
1622          VECTOR backupMV;          VECTOR backupMV;
1623    
1624          backupMV.x = startx;          backupMV.x = start_x;
1625          backupMV.y = starty;          backupMV.y = start_y;
1626    
1627  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
1628    
# Line 1569  Line 1631 
1631          CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);          CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);
1632          CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);          CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);
1633    
1634          if (iDirection)          if (iDirection) {
1635                  while (!iFound) {                  while (!iFound) {
1636                          iFound = 1;                          iFound = 1;
1637                          backupMV = *currMV;     // since iDirection!=0, this is well defined!                          backupMV = *currMV;     // since iDirection!=0, this is well defined!
1638                            iDirectionBackup = iDirection;
1639    
1640                          if (iDirection != 2)                          if (iDirectionBackup != 2)
1641                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1642                                                                                    backupMV.y, 1);                                                                                    backupMV.y, 1);
1643                          if (iDirection != 1)                          if (iDirectionBackup != 1)
1644                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1645                                                                                    backupMV.y, 2);                                                                                    backupMV.y, 2);
1646                          if (iDirection != 4)                          if (iDirectionBackup != 4)
1647                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1648                                                                                    backupMV.y - iDiamondSize, 3);                                                                                    backupMV.y - iDiamondSize, 3);
1649                          if (iDirection != 3)                          if (iDirectionBackup != 3)
1650                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1651                                                                                    backupMV.y + iDiamondSize, 4);                                                                                    backupMV.y + iDiamondSize, 4);
1652                    }
1653          } else {          } else {
1654                  currMV->x = startx;                  currMV->x = start_x;
1655                  currMV->y = starty;                  currMV->y = start_y;
1656          }          }
1657          return iMinSAD;          return iMinSAD;
1658  }  }
1659    
1660    
1661    
1662    
1663  int32_t  int32_t
1664  Halfpel8_Refine(const uint8_t * const pRef,  Square8_MainSearch(const uint8_t * const pRef,
1665                                  const uint8_t * const pRefH,                                  const uint8_t * const pRefH,
1666                                  const uint8_t * const pRefV,                                  const uint8_t * const pRefV,
1667                                  const uint8_t * const pRefHV,                                  const uint8_t * const pRefHV,
1668                                  const uint8_t * const cur,                                  const uint8_t * const cur,
1669                                  const int x,                                  const int x,
1670                                  const int y,                                  const int y,
1671                                  VECTOR * const currMV,                                          int32_t start_x,
1672                                            int32_t start_y,
1673                                  int32_t iMinSAD,                                  int32_t iMinSAD,
1674                                  const VECTOR * const pmv,                                          VECTOR * const currMV,
1675                                       const int center_x,
1676                                       const int center_y,
1677                                  const int32_t min_dx,                                  const int32_t min_dx,
1678                                  const int32_t max_dx,                                  const int32_t max_dx,
1679                                  const int32_t min_dy,                                  const int32_t min_dy,
1680                                  const int32_t max_dy,                                  const int32_t max_dy,
1681                                            const int32_t iEdgedWidth,
1682                                            const int32_t iDiamondSize,
1683                                  const int32_t iFcode,                                  const int32_t iFcode,
1684                                  const int32_t iQuant,                                  const int32_t iQuant,
1685                                  const int32_t iEdgedWidth)                                          int iFound)
1686  {  {
1687  /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */  /* Do a square search around given starting point, return SAD of best */
1688    
1689            int32_t iDirection = 0;
1690          int32_t iSAD;          int32_t iSAD;
1691          VECTOR backupMV = *currMV;          VECTOR backupMV;
1692    
1693          CHECK_MV8_CANDIDATE(backupMV.x - 1, backupMV.y - 1);          backupMV.x = start_x;
1694          CHECK_MV8_CANDIDATE(backupMV.x, backupMV.y - 1);          backupMV.y = start_y;
         CHECK_MV8_CANDIDATE(backupMV.x + 1, backupMV.y - 1);  
         CHECK_MV8_CANDIDATE(backupMV.x - 1, backupMV.y);  
         CHECK_MV8_CANDIDATE(backupMV.x + 1, backupMV.y);  
         CHECK_MV8_CANDIDATE(backupMV.x - 1, backupMV.y + 1);  
         CHECK_MV8_CANDIDATE(backupMV.x, backupMV.y + 1);  
         CHECK_MV8_CANDIDATE(backupMV.x + 1, backupMV.y + 1);  
1695    
1696          return iMinSAD;  /* It's one search with full square pattern, and new parts for all following diamonds */
 }  
1697    
1698    /*   new direction are extra, so 1-4 is normal diamond
1699          537
1700          1*2
1701          648
1702    */
1703    
1704  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)          CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y, 1);
1705            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y, 2);
1706            CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);
1707            CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);
1708    
1709  int32_t          CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize,
1710  PMVfastSearch8(const uint8_t * const pRef,                                                           backupMV.y - iDiamondSize, 5);
1711                             const uint8_t * const pRefH,          CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize,
1712                             const uint8_t * const pRefV,                                                           backupMV.y + iDiamondSize, 6);
1713                             const uint8_t * const pRefHV,          CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize,
1714                             const IMAGE * const pCur,                                                           backupMV.y - iDiamondSize, 7);
1715                             const int x,          CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize,
1716                             const int y,                                                           backupMV.y + iDiamondSize, 8);
                            const int start_x,  
                            const int start_y,  
                            const uint32_t MotionFlags,  
                            const uint32_t iQuant,  
                            const uint32_t iFcode,  
                            const MBParam * const pParam,  
                            const MACROBLOCK * const pMBs,  
                            const MACROBLOCK * const prevMBs,  
                            VECTOR * const currMV,  
                            VECTOR * const currPMV)  
 {  
         const uint32_t iWcount = pParam->mb_width;  
         const int32_t iWidth = pParam->width;  
         const int32_t iHeight = pParam->height;  
         const int32_t iEdgedWidth = pParam->edged_width;  
1717    
         const uint8_t *cur = pCur->y + x * 8 + y * 8 * iEdgedWidth;  
1718    
1719          int32_t iDiamondSize;          if (iDirection) {
1720                    while (!iFound) {
1721                            iFound = 1;
1722                            backupMV = *currMV;
1723    
1724          int32_t min_dx;                          switch (iDirection) {
1725          int32_t max_dx;                          case 1:
1726          int32_t min_dy;                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1727          int32_t max_dy;                                                                                     backupMV.y, 1);
1728                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1729                                                                                     backupMV.y - iDiamondSize, 5);
1730                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1731                                                                                     backupMV.y - iDiamondSize, 7);
1732                                    break;
1733                            case 2:
1734                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1735                                                                                     2);
1736                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1737                                                                                     backupMV.y + iDiamondSize, 6);
1738                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1739                                                                                     backupMV.y + iDiamondSize, 8);
1740                                    break;
1741    
1742          VECTOR pmv[4];                          case 3:
1743          int32_t psad[4];                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1744          VECTOR newMV;                                                                                   4);
1745          VECTOR backupMV;                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1746          VECTOR startMV;                                                                                   backupMV.y - iDiamondSize, 7);
1747                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1748                                                                                     backupMV.y + iDiamondSize, 8);
1749                                    break;
1750    
1751  //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;                          case 4:
1752          const MACROBLOCK *const prevMB = prevMBs + (x >> 1) + (y >> 1) * iWcount;                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1753                                                                                     3);
1754                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1755                                                                                     backupMV.y - iDiamondSize, 5);
1756                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1757                                                                                     backupMV.y + iDiamondSize, 6);
1758                                    break;
1759    
1760          static int32_t threshA, threshB;                          case 5:
1761          int32_t iFound, bPredEq;                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
1762          int32_t iMinSAD, iSAD;                                                                                   1);
1763                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1764                                                                                     3);
1765                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1766                                                                                     backupMV.y - iDiamondSize, 5);
1767                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1768                                                                                     backupMV.y + iDiamondSize, 6);
1769                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1770                                                                                     backupMV.y - iDiamondSize, 7);
1771                                    break;
1772    
1773                            case 6:
1774                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1775                                                                                     2);
1776                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1777                                                                                     3);
1778    
1779                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1780                                                                                     backupMV.y - iDiamondSize, 5);
1781                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1782                                                                                     backupMV.y + iDiamondSize, 6);
1783                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1784                                                                                     backupMV.y + iDiamondSize, 8);
1785    
1786                                    break;
1787    
1788                            case 7:
1789                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1790                                                                                       backupMV.y, 1);
1791                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1792                                                                                     4);
1793                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1794                                                                                     backupMV.y - iDiamondSize, 5);
1795                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1796                                                                                     backupMV.y - iDiamondSize, 7);
1797                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1798                                                                                     backupMV.y + iDiamondSize, 8);
1799                                    break;
1800    
1801                            case 8:
1802                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1803                                                                                     2);
1804                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1805                                                                                     4);
1806                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1807                                                                                     backupMV.y + iDiamondSize, 6);
1808                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1809                                                                                     backupMV.y - iDiamondSize, 7);
1810                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1811                                                                                     backupMV.y + iDiamondSize, 8);
1812                                    break;
1813                            default:
1814                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
1815                                                                                     1);
1816                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1817                                                                                     2);
1818                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1819                                                                                     3);
1820                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1821                                                                                     4);
1822    
1823                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1824                                                                                     backupMV.y - iDiamondSize, 5);
1825                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1826                                                                                     backupMV.y + iDiamondSize, 6);
1827                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1828                                                                                     backupMV.y - iDiamondSize, 7);
1829                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1830                                                                                     backupMV.y + iDiamondSize, 8);
1831                                    break;
1832                            }
1833                    }
1834            } else {
1835                    currMV->x = start_x;
1836                    currMV->y = start_y;
1837            }
1838            return iMinSAD;
1839    }
1840    
1841    
1842    
1843    
1844    
1845    int32_t
1846    Halfpel8_Refine_c(const uint8_t * const pRef,
1847                                    const uint8_t * const pRefH,
1848                                    const uint8_t * const pRefV,
1849                                    const uint8_t * const pRefHV,
1850                                    const uint8_t * const cur,
1851                                    const int x,
1852                                    const int y,
1853                                    VECTOR * const currMV,
1854                                    int32_t iMinSAD,
1855                               const int center_x,
1856                               const int center_y,
1857                                    const int32_t min_dx,
1858                                    const int32_t max_dx,
1859                                    const int32_t min_dy,
1860                                    const int32_t max_dy,
1861                                    const int32_t iFcode,
1862                                    const int32_t iQuant,
1863                                    const int32_t iEdgedWidth)
1864    {
1865    /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */
1866    
1867            int32_t iSAD;
1868            VECTOR backupMV = *currMV;
1869    
1870            CHECK_MV8_CANDIDATE(backupMV.x - 1, backupMV.y - 1);
1871            CHECK_MV8_CANDIDATE(backupMV.x, backupMV.y - 1);
1872            CHECK_MV8_CANDIDATE(backupMV.x + 1, backupMV.y - 1);
1873            CHECK_MV8_CANDIDATE(backupMV.x - 1, backupMV.y);
1874            CHECK_MV8_CANDIDATE(backupMV.x + 1, backupMV.y);
1875            CHECK_MV8_CANDIDATE(backupMV.x - 1, backupMV.y + 1);
1876            CHECK_MV8_CANDIDATE(backupMV.x, backupMV.y + 1);
1877            CHECK_MV8_CANDIDATE(backupMV.x + 1, backupMV.y + 1);
1878    
1879            return iMinSAD;
1880    }
1881    
1882    
1883    #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)
1884    
1885    int32_t
1886    PMVfastSearch8(const uint8_t * const pRef,
1887                               const uint8_t * const pRefH,
1888                               const uint8_t * const pRefV,
1889                               const uint8_t * const pRefHV,
1890                               const IMAGE * const pCur,
1891                               const int x,
1892                               const int y,
1893                               const int start_x,
1894                               const int start_y,
1895                                    const int center_x,
1896                                    const int center_y,
1897                               const uint32_t MotionFlags,
1898                               const uint32_t iQuant,
1899                               const uint32_t iFcode,
1900                               const MBParam * const pParam,
1901                               const MACROBLOCK * const pMBs,
1902                               const MACROBLOCK * const prevMBs,
1903                               VECTOR * const currMV,
1904                               VECTOR * const currPMV)
1905    {
1906            const uint32_t iWcount = pParam->mb_width;
1907            const int32_t iWidth = pParam->width;
1908            const int32_t iHeight = pParam->height;
1909            const int32_t iEdgedWidth = pParam->edged_width;
1910    
1911            const uint8_t *cur = pCur->y + x * 8 + y * 8 * iEdgedWidth;
1912    
1913            int32_t iDiamondSize;
1914    
1915            int32_t min_dx;
1916            int32_t max_dx;
1917            int32_t min_dy;
1918            int32_t max_dy;
1919    
1920            VECTOR pmv[4];
1921            int32_t psad[4];
1922            VECTOR newMV;
1923            VECTOR backupMV;
1924            VECTOR startMV;
1925    
1926    //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1927            const MACROBLOCK *const prevMB = prevMBs + (x >> 1) + (y >> 1) * iWcount;
1928    
1929             int32_t threshA, threshB;
1930            int32_t iFound, bPredEq;
1931            int32_t iMinSAD, iSAD;
1932    
1933          int32_t iSubBlock = (y & 1) + (y & 1) + (x & 1);          int32_t iSubBlock = (y & 1) + (y & 1) + (x & 1);
1934    
# Line 1698  Line 1950 
1950          }          }
1951    
1952          /* because we might use IF (dx>max_dx) THEN dx=max_dx; */          /* because we might use IF (dx>max_dx) THEN dx=max_dx; */
1953          bPredEq =          //bPredEq = get_pmvdata(pMBs, (x >> 1), (y >> 1), iWcount, iSubBlock, pmv, psad);
1954                  get_pmvdata(pMBs, (x >> 1), (y >> 1), iWcount, iSubBlock, pmv, psad, 0, 0);          bPredEq = get_pmvdata2(pMBs, iWcount, 0, (x >> 1), (y >> 1), iSubBlock, pmv, psad);
1955    
1956          if ((x == 0) && (y == 0)) {          if ((x == 0) && (y == 0)) {
1957                  threshA = 512 / 4;                  threshA = 512 / 4;
1958                  threshB = 1024 / 4;                  threshB = 1024 / 4;
1959    
1960          } else {          } else {
1961                  threshA = psad[0] / 4;  /* good estimate */                  threshA = psad[0] / 4;  /* good estimate? */
1962                  threshB = threshA + 256 / 4;                  threshB = threshA + 256 / 4;
1963                  if (threshA < 512 / 4)                  if (threshA < 512 / 4)
1964                          threshA = 512 / 4;                          threshA = 512 / 4;
# Line 1728  Line 1980 
1980    
1981  // Prepare for main loop  // Prepare for main loop
1982    
1983  //  if (MotionFlags & PMV_USESQUARES8)    if (MotionFlags & PMV_USESQUARES8)
1984  //      MainSearchPtr = Square8_MainSearch;        MainSearchPtr = Square8_MainSearch;
1985  //  else    else
1986    
1987          if (MotionFlags & PMV_ADVANCEDDIAMOND8)          if (MotionFlags & PMV_ADVANCEDDIAMOND8)
1988                  MainSearchPtr = AdvDiamond8_MainSearch;                  MainSearchPtr = AdvDiamond8_MainSearch;
# Line 1745  Line 1997 
1997                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
1998                                                  iEdgedWidth), iEdgedWidth);                                                  iEdgedWidth), iEdgedWidth);
1999          iMinSAD +=          iMinSAD +=
2000                  calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y,                  calc_delta_8(currMV->x - center_x, currMV->y - center_y,
2001                                           (uint8_t) iFcode, iQuant);                                           (uint8_t) iFcode, iQuant);
2002    
2003          if ((iMinSAD < 256 / 4) || ((MVequal(*currMV, prevMB->mvs[iSubBlock]))          if ((iMinSAD < 256 / 4) || ((MVequal(*currMV, prevMB->mvs[iSubBlock]))
2004                                                                  && ((uint32_t) iMinSAD <                                                                  && ((int32_t) iMinSAD <
2005                                                                          prevMB->sad8[iSubBlock]))) {                                                                          prevMB->sad8[iSubBlock]))) {
2006                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
2007                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
# Line 1788  Line 2040 
2040  // the median prediction might be even better than mv16  // the median prediction might be even better than mv16
2041    
2042          if (!MVequal(pmv[0], startMV))          if (!MVequal(pmv[0], startMV))
2043                  CHECK_MV8_CANDIDATE(pmv[0].x, pmv[0].y);                  CHECK_MV8_CANDIDATE(center_x, center_y);
2044    
2045  // (0,0) if needed  // (0,0) if needed
2046          if (!MVzero(pmv[0]))          if (!MVzero(pmv[0]))
# Line 1804  Line 2056 
2056    
2057          if ((iMinSAD <= threshA) ||          if ((iMinSAD <= threshA) ||
2058                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
2059                   ((uint32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {                   ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
2060                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
2061                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
2062                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1863  Line 2115 
2115    
2116          if ((iMinSAD <= threshA) ||          if ((iMinSAD <= threshA) ||
2117                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
2118                   ((uint32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {                   ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
2119                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
2120                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
2121                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1885  Line 2137 
2137  /* 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 */
2138          iSAD =          iSAD =
2139                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2140                                                    currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx,                                                    currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2141                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2142                                                    iQuant, iFound);                                                    iQuant, iFound);
2143    
# Line 1900  Line 2152 
2152                  if (!(MVequal(pmv[0], backupMV))) {                  if (!(MVequal(pmv[0], backupMV))) {
2153                          iSAD =                          iSAD =
2154                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2155                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, pmv,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2156                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2157                                                                    iDiamondSize, iFcode, iQuant, iFound);                                                                    iDiamondSize, iFcode, iQuant, iFound);
2158    
# Line 1913  Line 2165 
2165                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2166                          iSAD =                          iSAD =
2167                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2168                                                                    iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2169                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2170                                                                    iQuant, iFound);                                                                    iQuant, iFound);
2171    
# Line 1932  Line 2184 
2184          if (MotionFlags & PMV_HALFPELREFINE8)   // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)   // perform final half-pel step
2185                  iMinSAD =                  iMinSAD =
2186                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2187                                                          iMinSAD, pmv, min_dx, max_dx, min_dy, max_dy,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2188                                                          iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
2189    
2190    
2191    PMVfast8_Terminate_without_Refine:    PMVfast8_Terminate_without_Refine:
2192          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2193          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2194    
2195          return iMinSAD;          return iMinSAD;
2196  }  }
# Line 1951  Line 2203 
2203                           const IMAGE * const pCur,                           const IMAGE * const pCur,
2204                           const int x,                           const int x,
2205                           const int y,                           const int y,
2206                            const int start_x,
2207                            const int start_y,
2208                            const int center_x,
2209                            const int center_y,
2210                           const uint32_t MotionFlags,                           const uint32_t MotionFlags,
2211                           const uint32_t iQuant,                           const uint32_t iQuant,
2212                           const uint32_t iFcode,                           const uint32_t iFcode,
# Line 1986  Line 2242 
2242          const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;          const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
2243          MACROBLOCK *oldMB = NULL;          MACROBLOCK *oldMB = NULL;
2244    
2245          static int32_t thresh2;           int32_t thresh2;
2246          int32_t bPredEq;          int32_t bPredEq;
2247          int32_t iMinSAD, iSAD = 9999;          int32_t iMinSAD, iSAD = 9999;
2248    
# Line 2009  Line 2265 
2265                  max_dy = EVEN(max_dy);                  max_dy = EVEN(max_dy);
2266          }          }
2267          /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2268          bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad, 0, 0);          //bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
2269            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
2270    
2271  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
2272          MinSAD=SAD          MinSAD=SAD
# Line 2020  Line 2277 
2277    
2278  // Prepare for main loop  // Prepare for main loop
2279    
2280          *currMV = pmv[0];                       /* current best := median prediction */          currMV->x = start_x;
2281            currMV->y = start_y;
2282    
2283          if (!(MotionFlags & PMV_HALFPEL16)) {          if (!(MotionFlags & PMV_HALFPEL16)) {
2284                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
2285                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
# Line 2042  Line 2301 
2301                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
2302                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
2303          iMinSAD +=          iMinSAD +=
2304                  calc_delta_16(currMV->x - pmv[0].x, currMV->y - pmv[0].y,                  calc_delta_16(currMV->x - center_x, currMV->y - center_y,
2305                                            (uint8_t) iFcode, iQuant);                                            (uint8_t) iFcode, iQuant);
2306    
2307  // thresh1 is fixed to 256  // thresh1 is fixed to 256
2308          if ((iMinSAD < 256) ||          if ((iMinSAD < 256) ||
2309                  ((MVequal(*currMV, prevMB->mvs[0])) &&                  ((MVequal(*currMV, prevMB->mvs[0])) &&
2310                   ((uint32_t) iMinSAD < prevMB->sad16))) {                   ((int32_t) iMinSAD < prevMB->sad16))) {
2311                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
2312                          goto EPZS16_Terminate_without_Refine;                          goto EPZS16_Terminate_without_Refine;
2313                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 2108  Line 2367 
2367    
2368          if ((iMinSAD <= thresh2)          if ((iMinSAD <= thresh2)
2369                  || (MVequal(*currMV, prevMB->mvs[0]) &&                  || (MVequal(*currMV, prevMB->mvs[0]) &&
2370                          ((uint32_t) iMinSAD <= prevMB->sad16))) {                          ((int32_t) iMinSAD <= prevMB->sad16))) {
2371                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
2372                          goto EPZS16_Terminate_without_Refine;                          goto EPZS16_Terminate_without_Refine;
2373                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 2154  Line 2413 
2413    
2414          backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
2415    
2416          if (MotionFlags & PMV_USESQUARES8)          if (MotionFlags & PMV_USESQUARES16)
2417                  MainSearchPtr = Square16_MainSearch;                  MainSearchPtr = Square16_MainSearch;
2418          else          else
2419           if (MotionFlags & PMV_ADVANCEDDIAMOND8)           if (MotionFlags & PMV_ADVANCEDDIAMOND16)
2420                  MainSearchPtr = AdvDiamond16_MainSearch;                  MainSearchPtr = AdvDiamond16_MainSearch;
2421          else          else
2422                  MainSearchPtr = Diamond16_MainSearch;                  MainSearchPtr = Diamond16_MainSearch;
# Line 2166  Line 2425 
2425    
2426          iSAD =          iSAD =
2427                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2428                                                    currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx,                                                    currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2429                                                    min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);                                                    min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2430    
2431          if (iSAD < iMinSAD) {          if (iSAD < iMinSAD) {
# Line 2181  Line 2440 
2440                  if (!(MVequal(pmv[0], backupMV))) {                  if (!(MVequal(pmv[0], backupMV))) {
2441                          iSAD =                          iSAD =
2442                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2443                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, pmv,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2444                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2445                                                                    2, iFcode, iQuant, 0);                                                                    2, iFcode, iQuant, 0);
2446                  }                  }
# Line 2194  Line 2453 
2453                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2454                          iSAD =                          iSAD =
2455                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2456                                                                    iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2457                                                                    max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);                                                                    max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2458    
2459                          if (iSAD < iMinSAD) {                          if (iSAD < iMinSAD) {
# Line 2210  Line 2469 
2469          if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step
2470                  iMinSAD =                  iMinSAD =
2471                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2472                                                           iMinSAD, pmv, min_dx, max_dx, min_dy, max_dy,                                                           iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2473                                                           iFcode, iQuant, iEdgedWidth);                                                           iFcode, iQuant, iEdgedWidth);
2474    
2475    EPZS16_Terminate_without_Refine:    EPZS16_Terminate_without_Refine:
2476    
2477          *oldMB = *prevMB;          *oldMB = *prevMB;
2478    
2479          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2480          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2481          return iMinSAD;          return iMinSAD;
2482  }  }
2483    
# Line 2233  Line 2492 
2492                          const int y,                          const int y,
2493                          const int start_x,                          const int start_x,
2494                          const int start_y,                          const int start_y,
2495                            const int center_x,
2496                            const int center_y,
2497                          const uint32_t MotionFlags,                          const uint32_t MotionFlags,
2498                          const uint32_t iQuant,                          const uint32_t iQuant,
2499                          const uint32_t iFcode,                          const uint32_t iFcode,
# Line 2287  Line 2548 
2548                  max_dy = EVEN(max_dy);                  max_dy = EVEN(max_dy);
2549          }          }
2550          /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2551          bPredEq = get_pmvdata(pMBs, x >> 1, y >> 1, iWcount, iSubBlock, pmv, psad, 0, 0);          //bPredEq = get_pmvdata(pMBs, x >> 1, y >> 1, iWcount, iSubBlock, pmv[0].x, pmv[0].y, psad);
2552            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x >> 1, y >> 1, iSubBlock, pmv, psad);
2553    
2554    
2555  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
# Line 2322  Line 2584 
2584                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
2585                                                  iEdgedWidth), iEdgedWidth);                                                  iEdgedWidth), iEdgedWidth);
2586          iMinSAD +=          iMinSAD +=
2587                  calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y,                  calc_delta_8(currMV->x - center_x, currMV->y - center_y,
2588                                           (uint8_t) iFcode, iQuant);                                           (uint8_t) iFcode, iQuant);
2589    
2590    
# Line 2398  Line 2660 
2660    
2661  // there is no EPZS^2 for inter4v at the moment  // there is no EPZS^2 for inter4v at the moment
2662    
2663  //  if (MotionFlags & PMV_USESQUARES8)    if (MotionFlags & PMV_USESQUARES8)
2664  //      MainSearchPtr = Square8_MainSearch;        MainSearchPtr = Square8_MainSearch;
2665  //  else    else
2666    
2667          if (MotionFlags & PMV_ADVANCEDDIAMOND8)          if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2668                  MainSearchPtr = AdvDiamond8_MainSearch;                  MainSearchPtr = AdvDiamond8_MainSearch;
# Line 2409  Line 2671 
2671    
2672          iSAD =          iSAD =
2673                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2674                                                    currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx,                                                    currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2675                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2676                                                    iQuant, 0);                                                    iQuant, 0);
2677    
# Line 2425  Line 2687 
2687                  if (!(MVequal(pmv[0], backupMV))) {                  if (!(MVequal(pmv[0], backupMV))) {
2688                          iSAD =                          iSAD =
2689                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2690                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, pmv,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2691                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2692                                                                    iDiamondSize, iFcode, iQuant, 0);                                                                    iDiamondSize, iFcode, iQuant, 0);
2693    
# Line 2438  Line 2700 
2700                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2701                          iSAD =                          iSAD =
2702                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2703                                                                    iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2704                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2705                                                                    iQuant, 0);                                                                    iQuant, 0);
2706    
# Line 2455  Line 2717 
2717          if (MotionFlags & PMV_HALFPELREFINE8)   // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)   // perform final half-pel step
2718                  iMinSAD =                  iMinSAD =
2719                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2720                                                          iMinSAD, pmv, min_dx, max_dx, min_dy, max_dy,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2721                                                          iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
2722    
2723    EPZS8_Terminate_without_Refine:    EPZS8_Terminate_without_Refine:
2724    
2725          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2726          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2727          return iMinSAD;          return iMinSAD;
2728  }  }
2729    
2730    
2731    
2732    int32_t
2733    PMVfastIntSearch16(const uint8_t * const pRef,
2734                                    const uint8_t * const pRefH,
2735                                    const uint8_t * const pRefV,
2736                                    const uint8_t * const pRefHV,
2737                                    const IMAGE * const pCur,
2738                                    const int x,
2739                                    const int y,
2740                            const int start_x,
2741                            const int start_y,
2742                            const int center_x,
2743                            const int center_y,
2744                                    const uint32_t MotionFlags,
2745                                    const uint32_t iQuant,
2746                                    const uint32_t iFcode,
2747                                    const MBParam * const pParam,
2748                                    const MACROBLOCK * const pMBs,
2749                                    const MACROBLOCK * const prevMBs,
2750                                    VECTOR * const currMV,
2751                                    VECTOR * const currPMV)
2752    {
2753            const uint32_t iWcount = pParam->mb_width;
2754            const int32_t iWidth = pParam->width;
2755            const int32_t iHeight = pParam->height;
2756            const int32_t iEdgedWidth = pParam->edged_width;
2757    
2758            const uint8_t *cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;
2759            const VECTOR zeroMV = { 0, 0 };
2760    
2761            int32_t iDiamondSize;
2762    
2763            int32_t min_dx;
2764            int32_t max_dx;
2765            int32_t min_dy;
2766            int32_t max_dy;
2767    
2768            int32_t iFound;
2769    
2770            VECTOR newMV;
2771            VECTOR backupMV;                        /* just for PMVFAST */
2772    
2773            VECTOR pmv[4];
2774            int32_t psad[4];
2775    
2776            MainSearch16FuncPtr MainSearchPtr;
2777    
2778            const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
2779            MACROBLOCK *const pMB = pMBs + x + y * iWcount;
2780    
2781            int32_t threshA, threshB;
2782            int32_t bPredEq;
2783            int32_t iMinSAD, iSAD;
2784    
2785    
2786    /* Get maximum range */
2787            get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
2788                              iFcode);
2789    
2790    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
2791    
2792            if ((x == 0) && (y == 0)) {
2793                    threshA = 512;
2794                    threshB = 1024;
2795    
2796                    bPredEq = 0;
2797                    psad[0] = psad[1] = psad[2] = psad[3] = 0;
2798                    *currMV = pmv[0] = pmv[1] = pmv[2] = pmv[3] = zeroMV;
2799    
2800            } else {
2801                    threshA = psad[0];
2802                    threshB = threshA + 256;
2803                    if (threshA < 512)
2804                            threshA = 512;
2805                    if (threshA > 1024)
2806                            threshA = 1024;
2807                    if (threshB > 1792)
2808                            threshB = 1792;
2809    
2810                    bPredEq = get_ipmvdata(pMBs, iWcount, 0, x, y, 0, pmv, psad);
2811                    *currMV = pmv[0];                       /* current best := prediction */
2812            }
2813    
2814            iFound = 0;
2815    
2816    /* Step 4: Calculate SAD around the Median prediction.
2817       MinSAD=SAD
2818       If Motion Vector equal to Previous frame motion vector
2819       and MinSAD<PrevFrmSAD goto Step 10.
2820       If SAD<=256 goto Step 10.
2821    */
2822    
2823            if (currMV->x > max_dx) {
2824                    currMV->x = EVEN(max_dx);
2825            }
2826            if (currMV->x < min_dx) {
2827                    currMV->x = EVEN(min_dx);
2828            }
2829            if (currMV->y > max_dy) {
2830                    currMV->y = EVEN(max_dy);
2831            }
2832            if (currMV->y < min_dy) {
2833                    currMV->y = EVEN(min_dy);
2834            }
2835    
2836            iMinSAD =
2837                    sad16(cur,
2838                              get_iref_mv(pRef, x, y, 16, currMV,
2839                                                     iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
2840            iMinSAD +=
2841                    calc_delta_16(currMV->x - center_x, currMV->y - center_y,
2842                                              (uint8_t) iFcode, iQuant);
2843    
2844            if ((iMinSAD < 256) ||
2845                    ((MVequal(*currMV, prevMB->i_mvs[0])) &&
2846                     ((int32_t) iMinSAD < prevMB->i_sad16))) {
2847                    if (iMinSAD < 2 * iQuant)       // high chances for SKIP-mode
2848                    {
2849                            if (!MVzero(*currMV)) {
2850                                    iMinSAD += MV16_00_BIAS;
2851                                    CHECK_MV16_ZERO;        // (0,0) saves space for letterboxed pictures
2852                                    iMinSAD -= MV16_00_BIAS;
2853                            }
2854                    }
2855    
2856                    if (MotionFlags & PMV_EARLYSTOP16)
2857                            goto PMVfastInt16_Terminate_with_Refine;
2858            }
2859    
2860    
2861    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
2862       vector of the median.
2863       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
2864    */
2865    
2866            if ((bPredEq) && (MVequal(pmv[0], prevMB->i_mvs[0])))
2867                    iFound = 2;
2868    
2869    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
2870       Otherwise select large Diamond Search.
2871    */
2872    
2873            if ((!MVzero(pmv[0])) || (threshB < 1536) || (bPredEq))
2874                    iDiamondSize = 2;               // halfpel units!
2875            else
2876                    iDiamondSize = 4;               // halfpel units!
2877    
2878    /*
2879       Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.
2880       Also calculate (0,0) but do not subtract offset.
2881       Let MinSAD be the smallest SAD up to this point.
2882       If MV is (0,0) subtract offset.
2883    */
2884    
2885    // (0,0) is often a good choice
2886    
2887            if (!MVzero(pmv[0]))
2888                    CHECK_MV16_ZERO;
2889    
2890    // previous frame MV is always possible
2891    
2892            if (!MVzero(prevMB->i_mvs[0]))
2893                    if (!MVequal(prevMB->i_mvs[0], pmv[0]))
2894                            CHECK_MV16_CANDIDATE(prevMB->i_mvs[0].x, prevMB->i_mvs[0].y);
2895    
2896    // left neighbour, if allowed
2897    
2898            if (!MVzero(pmv[1]))
2899                    if (!MVequal(pmv[1], prevMB->i_mvs[0]))
2900                            if (!MVequal(pmv[1], pmv[0]))
2901                                    CHECK_MV16_CANDIDATE(pmv[1].x, pmv[1].y);
2902    
2903    // top neighbour, if allowed
2904            if (!MVzero(pmv[2]))
2905                    if (!MVequal(pmv[2], prevMB->i_mvs[0]))
2906                            if (!MVequal(pmv[2], pmv[0]))
2907                                    if (!MVequal(pmv[2], pmv[1]))
2908                                            CHECK_MV16_CANDIDATE(pmv[2].x, pmv[2].y);
2909    
2910    // top right neighbour, if allowed
2911                                            if (!MVzero(pmv[3]))
2912                                                    if (!MVequal(pmv[3], prevMB->i_mvs[0]))
2913                                                            if (!MVequal(pmv[3], pmv[0]))
2914                                                                    if (!MVequal(pmv[3], pmv[1]))
2915                                                                            if (!MVequal(pmv[3], pmv[2]))
2916                                                                                    CHECK_MV16_CANDIDATE(pmv[3].x,
2917                                                                                                                             pmv[3].y);
2918    
2919            if ((MVzero(*currMV)) &&
2920                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
2921                    iMinSAD -= MV16_00_BIAS;
2922    
2923    
2924    /* Step 6: If MinSAD <= thresa goto Step 10.
2925       If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
2926    */
2927    
2928            if ((iMinSAD <= threshA) ||
2929                    (MVequal(*currMV, prevMB->i_mvs[0]) &&
2930                     ((int32_t) iMinSAD < prevMB->i_sad16))) {
2931    
2932                    if (MotionFlags & PMV_EARLYSTOP16)
2933                            goto PMVfastInt16_Terminate_with_Refine;
2934            }
2935    
2936    
2937    /************ (Diamond Search)  **************/
2938    /*
2939       Step 7: Perform Diamond search, with either the small or large diamond.
2940       If Found=2 only examine one Diamond pattern, and afterwards goto step 10
2941       Step 8: If small diamond, iterate small diamond search pattern until motion vector lies in the center of the diamond.
2942       If center then goto step 10.
2943       Step 9: If large diamond, iterate large diamond search pattern until motion vector lies in the center.
2944       Refine by using small diamond and goto step 10.
2945    */
2946    
2947            if (MotionFlags & PMV_USESQUARES16)
2948                    MainSearchPtr = Square16_MainSearch;
2949            else if (MotionFlags & PMV_ADVANCEDDIAMOND16)
2950                    MainSearchPtr = AdvDiamond16_MainSearch;
2951            else
2952                    MainSearchPtr = Diamond16_MainSearch;
2953    
2954            backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
2955    
2956    
2957    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
2958            iSAD =
2959                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2960                                                      currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2961                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2962                                                      iQuant, iFound);
2963    
2964            if (iSAD < iMinSAD) {
2965                    *currMV = newMV;
2966                    iMinSAD = iSAD;
2967            }
2968    
2969            if (MotionFlags & PMV_EXTSEARCH16) {
2970    /* extended: search (up to) two more times: orignal prediction and (0,0) */
2971    
2972                    if (!(MVequal(pmv[0], backupMV))) {
2973                            iSAD =
2974                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2975                                                                      pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2976                                                                      min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2977                                                                      iDiamondSize, iFcode, iQuant, iFound);
2978    
2979                            if (iSAD < iMinSAD) {
2980                                    *currMV = newMV;
2981                                    iMinSAD = iSAD;
2982                            }
2983                    }
2984    
2985                    if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2986                            iSAD =
2987                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2988                                                                      iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2989                                                                      max_dy, iEdgedWidth, iDiamondSize, iFcode,
2990                                                                      iQuant, iFound);
2991    
2992                            if (iSAD < iMinSAD) {
2993                                    *currMV = newMV;
2994                                    iMinSAD = iSAD;
2995                            }
2996                    }
2997            }
2998    
2999    /*
3000       Step 10:  The motion vector is chosen according to the block corresponding to MinSAD.
3001    */
3002    
3003    PMVfastInt16_Terminate_with_Refine:
3004    
3005            pMB->i_mvs[0] = pMB->i_mvs[1] = pMB->i_mvs[2] = pMB->i_mvs[3] = pMB->i_mv16 = *currMV;
3006            pMB->i_sad8[0] = pMB->i_sad8[1] = pMB->i_sad8[2] = pMB->i_sad8[3] = pMB->i_sad16 = iMinSAD;
3007    
3008            if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step
3009                    iMinSAD =
3010                            Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
3011                                                             iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
3012                                                             iFcode, iQuant, iEdgedWidth);
3013    
3014            pmv[0] = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);          // get _REAL_ prediction (halfpel possible)
3015    
3016    PMVfastInt16_Terminate_without_Refine:
3017            currPMV->x = currMV->x - center_x;
3018            currPMV->y = currMV->y - center_y;
3019            return iMinSAD;
3020    }
3021    
3022    
3023    
3024  /* ***********************************************************  /* ***********************************************************
# Line 2475  Line 3027 
3027  ***************************************************************/  ***************************************************************/
3028    
3029    
3030    #define DIRECT_PENALTY 0
3031    #define DIRECT_UPPERLIMIT 256   // never use direct mode if SAD is larger than this
3032    
3033  void  void
3034  MotionEstimationBVOP(MBParam * const pParam,  MotionEstimationBVOP(MBParam * const pParam,
3035                                           FRAMEINFO * const frame,                                           FRAMEINFO * const frame,
3036                                             const int32_t time_bp,
3037                                             const int32_t time_pp,
3038                                           // forward (past) reference                                           // forward (past) reference
3039                                           const MACROBLOCK * const f_mbs,                                           const MACROBLOCK * const f_mbs,
3040                                           const IMAGE * const f_ref,                                           const IMAGE * const f_ref,
# Line 2491  Line 3048 
3048                                           const IMAGE * const b_refV,                                           const IMAGE * const b_refV,
3049                                           const IMAGE * const b_refHV)                                           const IMAGE * const b_refHV)
3050  {  {
3051          const uint32_t mb_width = pParam->mb_width;          const int mb_width = pParam->mb_width;
3052          const uint32_t mb_height = pParam->mb_height;          const int mb_height = pParam->mb_height;
3053          const int32_t edged_width = pParam->edged_width;          const int edged_width = pParam->edged_width;
3054    
3055          uint32_t i, j;          int i, j, k;
3056    
3057          int32_t f_sad16;          static const VECTOR zeroMV={0,0};
         int32_t b_sad16;  
         int32_t i_sad16;  
         int32_t d_sad16;  
         int32_t best_sad;  
3058    
3059            int f_sad16;    /* forward (as usual) search */
3060            int b_sad16;    /* backward (only in b-frames) search */
3061            int i_sad16;    /* interpolated (both direction, b-frames only) */
3062            int d_sad16;    /* direct mode (assume linear motion) */
3063    
3064            int best_sad;
3065    
3066            VECTOR f_predMV, b_predMV;      /* there is no prediction for direct mode*/
3067          VECTOR pmv_dontcare;          VECTOR pmv_dontcare;
3068    
3069            int f_count=0;
3070            int b_count=0;
3071            int i_count=0;
3072            int d_count=0;
3073            int s_count=0;
3074    
3075            const int64_t TRB = (int32_t)time_pp - (int32_t)time_bp;
3076        const int64_t TRD = (int32_t)time_pp;
3077    
3078            // fprintf(stderr,"TRB = %lld  TRD = %lld  time_bp =%d time_pp =%d\n\n",TRB,TRD,time_bp,time_pp);
3079          // note: i==horizontal, j==vertical          // note: i==horizontal, j==vertical
3080          for (j = 0; j < mb_height; j++) {          for (j = 0; j < mb_height; j++) {
3081    
3082                    f_predMV = zeroMV;      /* prediction is reset at left boundary */
3083                    b_predMV = zeroMV;
3084    
3085                  for (i = 0; i < mb_width; i++) {                  for (i = 0; i < mb_width; i++) {
3086                          MACROBLOCK *mb = &frame->mbs[i + j * mb_width];                          MACROBLOCK *mb = &frame->mbs[i + j * mb_width];
3087                          const MACROBLOCK *f_mb = &f_mbs[i + j * mb_width];                          const MACROBLOCK *f_mb = &f_mbs[i + j * mb_width];
3088                          const MACROBLOCK *b_mb = &b_mbs[i + j * mb_width];                          const MACROBLOCK *b_mb = &b_mbs[i + j * mb_width];
3089    
3090                            mb->deltamv=zeroMV;
3091    
3092    /* special case, if collocated block is SKIPed: encoding is forward(0,0)  */
3093    
3094    #ifndef _DISABLE_SKIP
3095                          if (b_mb->mode == MODE_INTER && b_mb->cbp == 0 &&                          if (b_mb->mode == MODE_INTER && b_mb->cbp == 0 &&
3096                                  b_mb->mvs[0].x == 0 && b_mb->mvs[0].y == 0) {                                  b_mb->mvs[0].x == 0 && b_mb->mvs[0].y == 0) {
3097                                  mb->mode = MODE_NOT_CODED;                                  mb->mode = MODE_NOT_CODED;
# Line 2521  Line 3101 
3101                                  mb->b_mvs[0].y = 0;                                  mb->b_mvs[0].y = 0;
3102                                  continue;                                  continue;
3103                          }                          }
3104                  /* force F_SAD16  #endif
                         f_sad16 = 100;  
                         b_sad16 = 65535;  
3105    
3106                          mb->mode = MODE_FORWARD;                          d_sad16 = DIRECT_PENALTY;
3107                          mb->mvs[0].x = 1;  
3108                          mb->mvs[0].y = 1;                          if (b_mb->mode == MODE_INTER4V)
3109                          mb->b_mvs[0].x = 1;                          {
3110                          mb->b_mvs[0].y = 1;  
3111                          continue;                          /* same method of scaling as in decoder.c, so we copy from there */
3112                   ^^ force F_SAD16 */                      for (k = 0; k < 4; k++) {
3113    
3114                                            mb->directmv[k] = b_mb->mvs[k];
3115    
3116                                            mb->mvs[k].x = (int32_t) ((TRB * mb->directmv[k].x) / TRD + mb->deltamv.x);
3117                        mb->b_mvs[k].x = (int32_t) ((mb->deltamv.x == 0)
3118                                                                                    ? ((TRB - TRD) * mb->directmv[k].x) / TRD
3119                                                : mb->mvs[k].x - mb->directmv[k].x);
3120    
3121                        mb->mvs[k].y = (int32_t) ((TRB * mb->directmv[k].y) / TRD + mb->deltamv.y);
3122                            mb->b_mvs[k].y = (int32_t) ((mb->directmv[k].y == 0)
3123                                                                                    ? ((TRB - TRD) * mb->directmv[k].y) / TRD
3124                                                : mb->mvs[k].y - mb->directmv[k].y);
3125    
3126                                            d_sad16 +=
3127                                                    sad8bi(frame->image.y + 2*(i+(k&1))*8 + 2*(j+(k>>1))*8*edged_width,
3128                                                      get_ref_mv(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3129                                                                    2*(i+(k&1)), 2*(j+(k>>1)), 8, &mb->mvs[k], edged_width),
3130                                                      get_ref_mv(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3131                                                                    2*(i+(k&1)), 2*(j+(k>>1)), 8, &mb->b_mvs[k], edged_width),
3132                                                      edged_width);
3133                                    }
3134                            }
3135                            else
3136                            {
3137                                    mb->directmv[3] = mb->directmv[2] = mb->directmv[1] =
3138                                    mb->directmv[0] = b_mb->mvs[0];
3139    
3140                                    mb->mvs[0].x = (int32_t) ((TRB * mb->directmv[0].x) / TRD + mb->deltamv.x);
3141                        mb->b_mvs[0].x = (int32_t) ((mb->deltamv.x == 0)
3142                                                                            ? ((TRB - TRD) * mb->directmv[0].x) / TRD
3143                                        : mb->mvs[0].x - mb->directmv[0].x);
3144    
3145                        mb->mvs[0].y = (int32_t) ((TRB * mb->directmv[0].y) / TRD + mb->deltamv.y);
3146                    mb->b_mvs[0].y = (int32_t) ((mb->directmv[0].y == 0)
3147                                                                            ? ((TRB - TRD) * mb->directmv[0].y) / TRD
3148                                        : mb->mvs[0].y - mb->directmv[0].y);
3149    
3150                                    d_sad16 += sad16bi(frame->image.y + i * 16 + j * 16 * edged_width,
3151                                                      get_ref_mv(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3152                                                                    i, j, 16, &mb->mvs[0], edged_width),
3153                                                      get_ref_mv(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3154                                                                    i, j, 16, &mb->b_mvs[0], edged_width),
3155                                                      edged_width);
3156    
3157                }
3158                        d_sad16 += calc_delta_16(mb->deltamv.x, mb->deltamv.y, 1, frame->quant);
3159    
3160                          // forward search                          // forward search
3161                          f_sad16 =                          f_sad16 = SEARCH16(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3162                                  SEARCH16(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,                                                  &frame->image, i, j,
3163                                                   &frame->image, i, j, frame->motion_flags,                                                  mb->mvs[0].x, mb->mvs[0].y,                     /* start point f_directMV */
3164                                                    f_predMV.x, f_predMV.y,                         /* center is f-prediction */
3165                                                    frame->motion_flags,
3166                                                   frame->quant, frame->fcode, pParam,                                                   frame->quant, frame->fcode, pParam,
3167                                                   f_mbs,  f_mbs, /* todo */                                                  f_mbs, f_mbs,
3168                                                   &mb->mvs[0], &pmv_dontcare);   // ignore pmv                                                  &mb->mvs[0], &pmv_dontcare);
3169    
3170    
3171                          // backward search                          // backward search
3172                          b_sad16 = SEARCH16(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,                          b_sad16 = SEARCH16(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3173                                                  &frame->image, i, j, frame->motion_flags,                                                  &frame->image, i, j,
3174                                                    mb->b_mvs[0].x, mb->b_mvs[0].y,         /* start point b_directMV */
3175                                                    b_predMV.x, b_predMV.y,                         /* center is b-prediction */
3176                                                    frame->motion_flags,
3177                                                  frame->quant, frame->bcode, pParam,                                                  frame->quant, frame->bcode, pParam,
3178                                                  b_mbs, b_mbs,   /* todo */                                                  b_mbs, b_mbs,
3179                                                  &mb->b_mvs[0], &pmv_dontcare);  // ignore pmv                                                  &mb->b_mvs[0], &pmv_dontcare);
   
                         // interpolate search (simple, but effective)  
                         i_sad16 = 65535;  
3180    
                         /*  
                         x/y range somewhat buggy  
3181                          i_sad16 =                          i_sad16 =
3182                                  sad16bi_c(frame->image.y + i * 16 + j * 16 * edged_width,                                  sad16bi(frame->image.y + i * 16 + j * 16 * edged_width,
3183                                                    get_ref(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,                                                    get_ref_mv(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3184                                                                    i, j, 16, mb->mvs[0].x, mb->mvs[0].y,                                                                  i, j, 16, &mb->mvs[0], edged_width),
3185                                                                    edged_width), get_ref(b_ref->y, b_refH->y,                                                    get_ref_mv(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3186                                                                                                                  b_refV->y, b_refHV->y,                                                                  i, j, 16, &mb->b_mvs[0], edged_width),
                                                                                                                 i, j, 16,  
                                                                                                                 mb->b_mvs[0].x,  
                                                                                                                 mb->b_mvs[0].x,  
                                                                                                                 edged_width),  
3187                                                    edged_width);                                                    edged_width);
3188                          */                      i_sad16 += calc_delta_16(mb->mvs[0].x-f_predMV.x, mb->mvs[0].y-f_predMV.y,
3189                                                                    frame->fcode, frame->quant);
3190                        i_sad16 += calc_delta_16(mb->b_mvs[0].x-b_predMV.x, mb->b_mvs[0].y-b_predMV.y,
3191                                                                    frame->bcode, frame->quant);
3192    
3193                          // TODO: direct search                          // TODO: direct search
3194                          // predictor + range of [-32,32]                          // predictor + delta vector in range [-32,32] (fcode=1)
                         d_sad16 = 65535;  
3195    
3196                            i_sad16 = 65535;
3197                            f_sad16 = 65535;
3198                            b_sad16 = 65535;
3199    //                      d_sad16 = 65535;
3200    
3201                          if (f_sad16 < b_sad16) {                          if (f_sad16 < b_sad16) {
3202                                  best_sad = f_sad16;                                  best_sad = f_sad16;
# Line 2586  Line 3212 
3212                          }                          }
3213    
3214                          if (d_sad16 < best_sad) {                          if (d_sad16 < best_sad) {
3215    
3216                                    if (b_mb->mode == MODE_INTER4V)
3217                                    {
3218    
3219                                    /* same method of scaling as in decoder.c, so we copy from there */
3220                                for (k = 0; k < 4; k++) {
3221    
3222                                                    mb->mvs[k].x = (int32_t) ((TRB * mb->directmv[k].x) / TRD + mb->deltamv.x);
3223                                mb->b_mvs[k].x = (int32_t) ((mb->deltamv.x == 0)
3224                                                                                            ? ((TRB - TRD) * mb->directmv[k].x) / TRD
3225                                                        : mb->mvs[k].x - mb->directmv[k].x);
3226    
3227                                mb->mvs[k].y = (int32_t) ((TRB * mb->directmv[k].y) / TRD + mb->deltamv.y);
3228                            mb->b_mvs[k].y = (int32_t) ((mb->directmv[k].y == 0)
3229                                                                                            ? ((TRB - TRD) * mb->directmv[k].y) / TRD
3230                                                : mb->mvs[k].y - mb->directmv[k].y);
3231                                            }
3232                                    }
3233                                    else
3234                                    {
3235                                            mb->mvs[0].x = (int32_t) ((TRB * mb->directmv[0].x) / TRD + mb->deltamv.x);
3236    
3237                        mb->b_mvs[0].x = (int32_t) ((mb->deltamv.x == 0)
3238                                                                                    ? ((TRB - TRD) * mb->directmv[0].x) / TRD
3239                                            : mb->mvs[0].x - mb->directmv[0].x);
3240    
3241                                mb->mvs[0].y = (int32_t) ((TRB * mb->directmv[0].y) / TRD + mb->deltamv.y);
3242    
3243                            mb->b_mvs[0].y = (int32_t) ((mb->directmv[0].y == 0)
3244                                                                                    ? ((TRB - TRD) * mb->directmv[0].y) / TRD
3245                                                : mb->mvs[0].y - mb->directmv[0].y);
3246    
3247                                            mb->mvs[3] = mb->mvs[2] = mb->mvs[1] = mb->mvs[0];
3248                                            mb->b_mvs[3] = mb->b_mvs[2] = mb->b_mvs[1] = mb->b_mvs[0];
3249                    }
3250    
3251                                  best_sad = d_sad16;                                  best_sad = d_sad16;
3252                                  mb->mode = MODE_DIRECT;                                  mb->mode = MODE_DIRECT;
3253                                    mb->mode = MODE_INTERPOLATE;            // direct mode still broken :-(
3254                            }
3255    
3256                            switch (mb->mode)
3257                            {
3258                                    case MODE_FORWARD:
3259                                            f_count++;
3260                                            f_predMV = mb->mvs[0];
3261                                            break;
3262                                    case MODE_BACKWARD:
3263                                            b_count++;
3264                                            b_predMV = mb->b_mvs[0];
3265    
3266                                            break;
3267                                    case MODE_INTERPOLATE:
3268                                            i_count++;
3269                                            f_predMV = mb->mvs[0];
3270                                            b_predMV = mb->b_mvs[0];
3271                                            break;
3272                                    case MODE_DIRECT:
3273                                            d_count++;
3274                                            break;
3275                                    default:
3276                                            s_count++;              // ???
3277                                            break;
3278                          }                          }
3279    
3280                  }                  }
3281          }          }
3282    
3283    #ifdef _DEBUG_BFRAME_STAT
3284            fprintf(stderr,"B-Stat: F: %04d   B: %04d   I: %04d  D: %04d   S: %04d\n",
3285                                    f_count,b_count,i_count,d_count,s_count);
3286    #endif
3287    
3288  }  }

Legend:
Removed from v.248  
changed lines
  Added in v.345

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