[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 252, Sun Jun 30 10:46:29 2002 UTC revision 351, Wed Jul 31 10:08:58 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    
877    #define CHECK_MV16_F_INTERPOL(X,Y) { \
878      if ( ((X) <= f_max_dx) && ((X) >= f_min_dx) \
879        && ((Y) <= f_max_dy) && ((Y) >= f_min_dy) ) \
880      { \
881        iSAD = sad16bi( cur, \
882                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
883                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, b_currMV->x, b_currMV->y, iEdgedWidth),   \
884                            iEdgedWidth); \
885        iSAD += calc_delta_16((X) - f_center_x, (Y) - f_center_y, (uint8_t)f_iFcode, iQuant);\
886        iSAD += calc_delta_16(b_currMV->x - b_center_x, b_currMV->y - b_center_y, (uint8_t)b_iFcode, iQuant);\
887        if (iSAD < iMinSAD) \
888        {  iMinSAD=iSAD; f_currMV->x=(X); f_currMV->y=(Y); } } \
889    }
890    
891    #define CHECK_MV16_F_INTERPOL_FOUND(X,Y) { \
892      if ( ((X) <= f_max_dx) && ((X) >= f_min_dx) \
893        && ((Y) <= f_max_dy) && ((Y) >= f_min_dy) ) \
894      { \
895        iSAD = sad16bi( cur, \
896                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
897                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, b_currMV->x, b_currMV->y, iEdgedWidth),   \
898                            iEdgedWidth); \
899        iSAD += calc_delta_16((X) - f_center_x, (Y) - f_center_y, (uint8_t)f_iFcode, iQuant);\
900        iSAD += calc_delta_16(b_currMV->x - b_center_x, b_currMV->y - b_center_y, (uint8_t)b_iFcode, iQuant);\
901        if (iSAD < iMinSAD) \
902        {  iMinSAD=iSAD; f_currMV->x=(X); f_currMV->y=(Y); iFound=0;} } \
903    }
904    
905    #define CHECK_MV16_B_INTERPOL(X,Y) { \
906      if ( ((X) <= b_max_dx) && ((X) >= b_min_dx) \
907        && ((Y) <= b_max_dy) && ((Y) >= b_min_dy) ) \
908      { \
909        iSAD = sad16bi( cur, \
910                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, f_currMV->x, f_currMV->y, iEdgedWidth),   \
911                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
912                            iEdgedWidth); \
913        iSAD += calc_delta_16(f_currMV->x - f_center_x, f_currMV->y - f_center_y, (uint8_t)f_iFcode, iQuant);\
914        iSAD += calc_delta_16((X) - b_center_x, (Y) - b_center_y, (uint8_t)b_iFcode, iQuant);\
915        if (iSAD < iMinSAD) \
916        {  iMinSAD=iSAD; b_currMV->x=(X); b_currMV->y=(Y); } } \
917    }
918    
919    #define CHECK_MV16_B_INTERPOL_FOUND(X,Y) { \
920      if ( ((X) <= b_max_dx) && ((X) >= b_min_dx) \
921        && ((Y) <= b_max_dy) && ((Y) >= b_min_dy) ) \
922      { \
923        iSAD = sad16bi( cur, \
924                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, f_currMV->x, f_currMV->y, iEdgedWidth),   \
925                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
926                            iEdgedWidth); \
927        iSAD += calc_delta_16(f_currMV->x - f_center_x, f_currMV->y - f_center_y, (uint8_t)f_iFcode, iQuant);\
928        iSAD += calc_delta_16((X) - b_center_x, (Y) - b_center_y, (uint8_t)b_iFcode, iQuant);\
929        if (iSAD < iMinSAD) \
930        {  iMinSAD=iSAD; b_currMV->x=(X); b_currMV->y=(Y); iFound=0;} } \
931    }
932    
933  int32_t  int32_t
934  AdvDiamond8_MainSearch(const uint8_t * const pRef,  Diamond16_InterpolMainSearch(
935                                             const uint8_t * const pRefH,                                          const uint8_t * const f_pRef,
936                                             const uint8_t * const pRefV,                                           const uint8_t * const f_pRefH,
937                                             const uint8_t * const pRefHV,                                           const uint8_t * const f_pRefV,
938                                             const uint8_t * const f_pRefHV,
939    
940                                             const uint8_t * const cur,                                             const uint8_t * const cur,
941    
942                                            const uint8_t * const b_pRef,
943                                             const uint8_t * const b_pRefH,
944                                             const uint8_t * const b_pRefV,
945                                             const uint8_t * const b_pRefHV,
946    
947                                             const int x,                                             const int x,
948                                             const int y,                                             const int y,
949                                             int32_t startx,  
950                                             int32_t starty,                                     const int f_start_x,
951                                             int32_t iMinSAD,                                     const int f_start_y,
952                                             VECTOR * const currMV,                                     const int b_start_x,
953                                             const VECTOR * const pmv,                                     const int b_start_y,
954                                             const int32_t min_dx,  
955                                             const int32_t max_dx,                                     int iMinSAD,
956                                             const int32_t min_dy,                                     VECTOR * const f_currMV,
957                                             const int32_t max_dy,                                     VECTOR * const b_currMV,
958    
959                                       const int f_center_x,
960                                       const int f_center_y,
961                                       const int b_center_x,
962                                       const int b_center_y,
963    
964                                        const int32_t f_min_dx,
965                                            const int32_t f_max_dx,
966                                            const int32_t f_min_dy,
967                                            const int32_t f_max_dy,
968    
969                                        const int32_t b_min_dx,
970                                            const int32_t b_max_dx,
971                                            const int32_t b_min_dy,
972                                            const int32_t b_max_dy,
973    
974                                             const int32_t iEdgedWidth,                                             const int32_t iEdgedWidth,
975                                             const int32_t iDiamondSize,                                             const int32_t iDiamondSize,
976                                             const int32_t iFcode,  
977                                            const int32_t f_iFcode,
978                                            const int32_t b_iFcode,
979    
980                                             const int32_t iQuant,                                             const int32_t iQuant,
981                                             int iDirection)                                          int iFound)
982  {  {
983    /* Do a diamond search around given starting point, return SAD of best */
984    
985          int32_t iSAD;          int32_t iSAD;
986    
987  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */          VECTOR f_backupMV;
988            VECTOR b_backupMV;
989    
990          if (iDirection) {          f_currMV->x = f_start_x;
991                  CHECK_MV8_CANDIDATE(startx - iDiamondSize, starty);          f_currMV->y = f_start_y;
992                  CHECK_MV8_CANDIDATE(startx + iDiamondSize, starty);          b_currMV->x = b_start_x;
993                  CHECK_MV8_CANDIDATE(startx, starty - iDiamondSize);          b_currMV->y = b_start_y;
                 CHECK_MV8_CANDIDATE(startx, starty + iDiamondSize);  
         } else {  
                 int bDirection = 1 + 2 + 4 + 8;  
994    
995                  do {          do
996                          iDirection = 0;          {
997                          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)                  iFound = 1;
                                 CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize, starty, 1);  
998    
999                          if (bDirection & 2)                  f_backupMV = *f_currMV;
                                 CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize, starty, 2);  
1000    
1001                          if (bDirection & 4)                  CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x - iDiamondSize, f_backupMV.y);
1002                                  CHECK_MV8_CANDIDATE_DIR(startx, starty - iDiamondSize, 4);                  CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x + iDiamondSize, f_backupMV.y);
1003                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x, f_backupMV.y - iDiamondSize);
1004                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x, f_backupMV.y + iDiamondSize);
1005    
1006                          if (bDirection & 8)                  b_backupMV = *b_currMV;
1007                                  CHECK_MV8_CANDIDATE_DIR(startx, starty + iDiamondSize, 8);  
1008                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x - iDiamondSize, b_backupMV.y);
1009                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x + iDiamondSize, b_backupMV.y);
1010                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x, b_backupMV.y - iDiamondSize);
1011                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x, b_backupMV.y + iDiamondSize);
1012    
1013            } while (!iFound);
1014    
1015            return iMinSAD;
1016    }
1017    
1018    /* Sorry, these MACROS really got too large... I'll turn them into function soon! */
1019    
1020    #define CHECK_MV16_DIRECT_FOUND(X,Y) \
1021            if ( (X)>=(-32) && (X)<=(31) && ((Y)>=-32) && ((Y)<=31) ) \
1022            { int k;\
1023            VECTOR mvs,b_mvs;       \
1024            iSAD = 0;\
1025            for (k = 0; k < 4; k++) {       \
1026                                            mvs.x = (int32_t) ((TRB * directmv[k].x) / TRD + (X));          \
1027                        b_mvs.x = (int32_t) (((X) == 0)                                                     \
1028                                                                                    ? ((TRB - TRD) * directmv[k].x) / TRD   \
1029                                                : mvs.x - directmv[k].x);                           \
1030                                                                                                                                                                    \
1031                        mvs.y = (int32_t) ((TRB * directmv[k].y) / TRD + (Y));              \
1032                            b_mvs.y = (int32_t) (((Y) == 0)                                                         \
1033                                                                                    ? ((TRB - TRD) * directmv[k].y) / TRD   \
1034                                                : mvs.y - directmv[k].y);                           \
1035                                                                                                                                                                    \
1036      if ( (mvs.x <= max_dx) && (mvs.x >= min_dx) \
1037        && (mvs.y <= max_dy) && (mvs.y >= min_dy)  \
1038            && (b_mvs.x <= max_dx) && (b_mvs.x >= min_dx)  \
1039        && (b_mvs.y <= max_dy) && (b_mvs.y >= min_dy) ) { \
1040                iSAD += sad8bi( cur + 8*(k&1) + 8*(k>>1)*iEdgedWidth,                                                                                                       \
1041                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, 2*x+(k&1), 2*y+(k>>1), 8, \
1042                                            mvs.x, mvs.y, iEdgedWidth),                                                             \
1043                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, 2*x+(k&1), 2*y+(k>>1), 8, \
1044                                            b_mvs.x, b_mvs.y, iEdgedWidth),                                                         \
1045                            iEdgedWidth); \
1046                    }       \
1047            else    \
1048                    iSAD = 65535;   \
1049            } \
1050            iSAD += calc_delta_16((X),(Y), 1, iQuant);\
1051            if (iSAD < iMinSAD) \
1052                {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iFound=0; } \
1053    }
1054    
1055    
1056    
1057    int32_t
1058    Diamond16_DirectMainSearch(
1059                                            const uint8_t * const f_pRef,
1060                                            const uint8_t * const f_pRefH,
1061                                            const uint8_t * const f_pRefV,
1062                                            const uint8_t * const f_pRefHV,
1063    
1064                                            const uint8_t * const cur,
1065    
1066                                            const uint8_t * const b_pRef,
1067                                            const uint8_t * const b_pRefH,
1068                                            const uint8_t * const b_pRefV,
1069                                            const uint8_t * const b_pRefHV,
1070    
1071                                            const int x,
1072                                            const int y,
1073    
1074                                            const int TRB,
1075                                            const int TRD,
1076    
1077                                        const int start_x,
1078                                        const int start_y,
1079    
1080                                        int iMinSAD,
1081                                        VECTOR * const currMV,
1082                                            const VECTOR * const directmv,
1083    
1084                                        const int32_t min_dx,
1085                                            const int32_t max_dx,
1086                                            const int32_t min_dy,
1087                                            const int32_t max_dy,
1088    
1089                                            const int32_t iEdgedWidth,
1090                                            const int32_t iDiamondSize,
1091    
1092                                            const int32_t iQuant,
1093                                            int iFound)
1094    {
1095    /* Do a diamond search around given starting point, return SAD of best */
1096    
1097            int32_t iSAD;
1098    
1099            VECTOR backupMV;
1100    
1101            currMV->x = start_x;
1102            currMV->y = start_y;
1103    
1104    /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
1105    
1106            do
1107            {
1108                    iFound = 1;
1109    
1110                    backupMV = *currMV;
1111    
1112                    CHECK_MV16_DIRECT_FOUND(backupMV.x - iDiamondSize, backupMV.y);
1113                    CHECK_MV16_DIRECT_FOUND(backupMV.x + iDiamondSize, backupMV.y);
1114                    CHECK_MV16_DIRECT_FOUND(backupMV.x, backupMV.y - iDiamondSize);
1115                    CHECK_MV16_DIRECT_FOUND(backupMV.x, backupMV.y + iDiamondSize);
1116    
1117            } while (!iFound);
1118    
1119            return iMinSAD;
1120    }
1121    
1122    
1123    int32_t
1124    AdvDiamond8_MainSearch(const uint8_t * const pRef,
1125                                               const uint8_t * const pRefH,
1126                                               const uint8_t * const pRefV,
1127                                               const uint8_t * const pRefHV,
1128                                               const uint8_t * const cur,
1129                                               const int x,
1130                                               const int y,
1131                                               int start_x,
1132                                               int start_y,
1133                                               int iMinSAD,
1134                                               VECTOR * const currMV,
1135                                               const int center_x,
1136                                               const int center_y,
1137                                               const int32_t min_dx,
1138                                               const int32_t max_dx,
1139                                               const int32_t min_dy,
1140                                               const int32_t max_dy,
1141                                               const int32_t iEdgedWidth,
1142                                               const int32_t iDiamondSize,
1143                                               const int32_t iFcode,
1144                                               const int32_t iQuant,
1145                                               int iDirection)
1146    {
1147    
1148            int32_t iSAD;
1149    
1150    /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
1151    
1152            if (iDirection) {
1153                    CHECK_MV8_CANDIDATE(start_x - iDiamondSize, start_y);
1154                    CHECK_MV8_CANDIDATE(start_x + iDiamondSize, start_y);
1155                    CHECK_MV8_CANDIDATE(start_x, start_y - iDiamondSize);
1156                    CHECK_MV8_CANDIDATE(start_x, start_y + iDiamondSize);
1157            } else {
1158                    int bDirection = 1 + 2 + 4 + 8;
1159    
1160                    do {
1161                            iDirection = 0;
1162                            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)
1163                                    CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
1164    
1165                            if (bDirection & 2)
1166                                    CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
1167    
1168                            if (bDirection & 4)
1169                                    CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
1170    
1171                            if (bDirection & 8)
1172                                    CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
1173    
1174                          /* now we're doing diagonal checks near our candidate */                          /* now we're doing diagonal checks near our candidate */
1175    
# Line 1038  Line 1177 
1177                          {                          {
1178                                  bDirection = iDirection;                                  bDirection = iDirection;
1179                                  iDirection = 0;                                  iDirection = 0;
1180                                  startx = currMV->x;                                  start_x = currMV->x;
1181                                  starty = currMV->y;                                  start_y = currMV->y;
1182                                  if (bDirection & 3)     //our candidate is left or right                                  if (bDirection & 3)     //our candidate is left or right
1183                                  {                                  {
1184                                          CHECK_MV8_CANDIDATE_DIR(startx, starty + iDiamondSize, 8);                                          CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
1185                                          CHECK_MV8_CANDIDATE_DIR(startx, starty - iDiamondSize, 4);                                          CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
1186                                  } else                  // what remains here is up or down                                  } else                  // what remains here is up or down
1187                                  {                                  {
1188                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize, starty, 2);                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
1189                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize, starty, 1);                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
1190                                  }                                  }
1191    
1192                                  if (iDirection) {                                  if (iDirection) {
1193                                          bDirection += iDirection;                                          bDirection += iDirection;
1194                                          startx = currMV->x;                                          start_x = currMV->x;
1195                                          starty = currMV->y;                                          start_y = currMV->y;
1196                                  }                                  }
1197                          } else                          //about to quit, eh? not so fast....                          } else                          //about to quit, eh? not so fast....
1198                          {                          {
1199                                  switch (bDirection) {                                  switch (bDirection) {
1200                                  case 2:                                  case 2:
1201                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1202                                                                                          starty - iDiamondSize, 2 + 4);                                                                                          start_y - iDiamondSize, 2 + 4);
1203                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1204                                                                                          starty + iDiamondSize, 2 + 8);                                                                                          start_y + iDiamondSize, 2 + 8);
1205                                          break;                                          break;
1206                                  case 1:                                  case 1:
1207                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1208                                                                                          starty - iDiamondSize, 1 + 4);                                                                                          start_y - iDiamondSize, 1 + 4);
1209                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1210                                                                                          starty + iDiamondSize, 1 + 8);                                                                                          start_y + iDiamondSize, 1 + 8);
1211                                          break;                                          break;
1212                                  case 2 + 4:                                  case 2 + 4:
1213                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1214                                                                                          starty - iDiamondSize, 1 + 4);                                                                                          start_y - iDiamondSize, 1 + 4);
1215                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1216                                                                                          starty - iDiamondSize, 2 + 4);                                                                                          start_y - iDiamondSize, 2 + 4);
1217                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1218                                                                                          starty + iDiamondSize, 2 + 8);                                                                                          start_y + iDiamondSize, 2 + 8);
1219                                          break;                                          break;
1220                                  case 4:                                  case 4:
1221                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1222                                                                                          starty - iDiamondSize, 2 + 4);                                                                                          start_y - iDiamondSize, 2 + 4);
1223                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1224                                                                                          starty - iDiamondSize, 1 + 4);                                                                                          start_y - iDiamondSize, 1 + 4);
1225                                          break;                                          break;
1226                                  case 8:                                  case 8:
1227                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1228                                                                                          starty + iDiamondSize, 2 + 8);                                                                                          start_y + iDiamondSize, 2 + 8);
1229                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1230                                                                                          starty + iDiamondSize, 1 + 8);                                                                                          start_y + iDiamondSize, 1 + 8);
1231                                          break;                                          break;
1232                                  case 1 + 4:                                  case 1 + 4:
1233                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1234                                                                                          starty + iDiamondSize, 1 + 8);                                                                                          start_y + iDiamondSize, 1 + 8);
1235                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1236                                                                                          starty - iDiamondSize, 1 + 4);                                                                                          start_y - iDiamondSize, 1 + 4);
1237                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1238                                                                                          starty - iDiamondSize, 2 + 4);                                                                                          start_y - iDiamondSize, 2 + 4);
1239                                          break;                                          break;
1240                                  case 2 + 8:                                  case 2 + 8:
1241                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1242                                                                                          starty - iDiamondSize, 1 + 4);                                                                                          start_y - iDiamondSize, 1 + 4);
1243                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1244                                                                                          starty + iDiamondSize, 1 + 8);                                                                                          start_y + iDiamondSize, 1 + 8);
1245                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1246                                                                                          starty + iDiamondSize, 2 + 8);                                                                                          start_y + iDiamondSize, 2 + 8);
1247                                          break;                                          break;
1248                                  case 1 + 8:                                  case 1 + 8:
1249                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1250                                                                                          starty - iDiamondSize, 2 + 4);                                                                                          start_y - iDiamondSize, 2 + 4);
1251                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1252                                                                                          starty + iDiamondSize, 2 + 8);                                                                                          start_y + iDiamondSize, 2 + 8);
1253                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1254                                                                                          starty + iDiamondSize, 1 + 8);                                                                                          start_y + iDiamondSize, 1 + 8);
1255                                          break;                                          break;
1256                                  default:                //1+2+4+8 == we didn't find anything at all                                  default:                //1+2+4+8 == we didn't find anything at all
1257                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1258                                                                                          starty - iDiamondSize, 1 + 4);                                                                                          start_y - iDiamondSize, 1 + 4);
1259                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1260                                                                                          starty + iDiamondSize, 1 + 8);                                                                                          start_y + iDiamondSize, 1 + 8);
1261                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1262                                                                                          starty - iDiamondSize, 2 + 4);                                                                                          start_y - iDiamondSize, 2 + 4);
1263                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1264                                                                                          starty + iDiamondSize, 2 + 8);                                                                                          start_y + iDiamondSize, 2 + 8);
1265                                          break;                                          break;
1266                                  }                                  }
1267                                  if (!(iDirection))                                  if (!(iDirection))
1268                                          break;          //ok, the end. really                                          break;          //ok, the end. really
1269                                  else {                                  else {
1270                                          bDirection = iDirection;                                          bDirection = iDirection;
1271                                          startx = currMV->x;                                          start_x = currMV->x;
1272                                          starty = currMV->y;                                          start_y = currMV->y;
1273                                  }                                  }
1274                          }                          }
1275                  }                  }
# Line 1148  Line 1287 
1287                                   const uint8_t * const cur,                                   const uint8_t * const cur,
1288                                   const int x,                                   const int x,
1289                                   const int y,                                   const int y,
1290                                   int32_t startx,                             const int start_x,
1291                                   int32_t starty,                             const int start_y,
1292                                   int32_t iMinSAD,                             int iMinSAD,
1293                                   VECTOR * const currMV,                                   VECTOR * const currMV,
1294                                   const VECTOR * const pmv,                             const int center_x,
1295                               const int center_y,
1296                                   const int32_t min_dx,                                   const int32_t min_dx,
1297                                   const int32_t max_dx,                                   const int32_t max_dx,
1298                                   const int32_t min_dy,                                   const int32_t min_dy,
# Line 1167  Line 1307 
1307          int32_t dx, dy;          int32_t dx, dy;
1308          VECTOR backupMV;          VECTOR backupMV;
1309    
1310          backupMV.x = startx;          backupMV.x = start_x;
1311          backupMV.y = starty;          backupMV.y = start_y;
1312    
1313          for (dx = min_dx; dx <= max_dx; dx += iDiamondSize)          for (dx = min_dx; dx <= max_dx; dx += iDiamondSize)
1314                  for (dy = min_dy; dy <= max_dy; dy += iDiamondSize)                  for (dy = min_dy; dy <= max_dy; dy += iDiamondSize)
# Line 1177  Line 1317 
1317          return iMinSAD;          return iMinSAD;
1318  }  }
1319    
1320    Halfpel8_RefineFuncPtr Halfpel8_Refine;
1321    
1322  int32_t  int32_t
1323  Halfpel16_Refine(const uint8_t * const pRef,  Halfpel16_Refine(const uint8_t * const pRef,
# Line 1189  Line 1329 
1329                                   const int y,                                   const int y,
1330                                   VECTOR * const currMV,                                   VECTOR * const currMV,
1331                                   int32_t iMinSAD,                                   int32_t iMinSAD,
1332                                   const VECTOR * const pmv,                             const int center_x,
1333                               const int center_y,
1334                                   const int32_t min_dx,                                   const int32_t min_dx,
1335                                   const int32_t max_dx,                                   const int32_t max_dx,
1336                                   const int32_t min_dy,                                   const int32_t min_dy,
# Line 1218  Line 1359 
1359  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
1360    
1361    
1362    
1363  int32_t  int32_t
1364  PMVfastSearch16(const uint8_t * const pRef,  PMVfastSearch16(const uint8_t * const pRef,
1365                                  const uint8_t * const pRefH,                                  const uint8_t * const pRefH,
# Line 1226  Line 1368 
1368                                  const IMAGE * const pCur,                                  const IMAGE * const pCur,
1369                                  const int x,                                  const int x,
1370                                  const int y,                                  const int y,
1371                                    const int start_x,      /* start is searched first, so it should contain the most */
1372                                    const int start_y,  /* likely motion vector for this block */
1373                                    const int center_x,     /* center is from where length of MVs is measured */
1374                                    const int center_y,
1375                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
1376                                  const uint32_t iQuant,                                  const uint32_t iQuant,
1377                                  const uint32_t iFcode,                                  const uint32_t iFcode,
# Line 1259  Line 1405 
1405    
1406          MainSearch16FuncPtr MainSearchPtr;          MainSearch16FuncPtr MainSearchPtr;
1407    
 //  const MACROBLOCK * const pMB = pMBs + x + y * iWcount;  
1408          const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;          const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
1409    
1410          static int32_t threshA, threshB;          int32_t threshA, threshB;
1411          int32_t bPredEq;          int32_t bPredEq;
1412          int32_t iMinSAD, iSAD;          int32_t iMinSAD, iSAD;
1413    
# Line 1280  Line 1425 
1425          }          }
1426    
1427          /* 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; */
1428          bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          //bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
1429            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
1430    
1431          if ((x == 0) && (y == 0)) {          if ((x == 0) && (y == 0)) {
1432                  threshA = 512;                  threshA = 512;
1433                  threshB = 1024;                  threshB = 1024;
   
1434          } else {          } else {
1435                  threshA = psad[0];                  threshA = psad[0];
1436                  threshB = threshA + 256;                  threshB = threshA + 256;
# Line 1306  Line 1451 
1451     If SAD<=256 goto Step 10.     If SAD<=256 goto Step 10.
1452  */  */
1453    
1454          *currMV = pmv[0];                       /* current best := prediction */          currMV->x = start_x;
1455            currMV->y = start_y;
1456    
1457          if (!(MotionFlags & PMV_HALFPEL16)) {   /* This should NOT be necessary! */          if (!(MotionFlags & PMV_HALFPEL16)) {   /* This should NOT be necessary! */
1458                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
1459                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
# Line 1330  Line 1477 
1477                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
1478                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
1479          iMinSAD +=          iMinSAD +=
1480                  calc_delta_16(currMV->x - pmv[0].x, currMV->y - pmv[0].y,                  calc_delta_16(currMV->x - center_x, currMV->y - center_y,
1481                                            (uint8_t) iFcode, iQuant);                                            (uint8_t) iFcode, iQuant);
1482    
1483          if ((iMinSAD < 256) ||          if ((iMinSAD < 256) ||
1484                  ((MVequal(*currMV, prevMB->mvs[0])) &&                  ((MVequal(*currMV, prevMB->mvs[0])) &&
1485                   ((uint32_t) iMinSAD < prevMB->sad16))) {                   ((int32_t) iMinSAD < prevMB->sad16))) {
1486                  if (iMinSAD < 2 * iQuant)       // high chances for SKIP-mode                  if (iMinSAD < 2 * iQuant)       // high chances for SKIP-mode
1487                  {                  {
1488                          if (!MVzero(*currMV)) {                          if (!MVzero(*currMV)) {
# Line 1439  Line 1586 
1586    
1587          if ((iMinSAD <= threshA) ||          if ((iMinSAD <= threshA) ||
1588                  (MVequal(*currMV, prevMB->mvs[0]) &&                  (MVequal(*currMV, prevMB->mvs[0]) &&
1589                   ((uint32_t) iMinSAD < prevMB->sad16))) {                   ((int32_t) iMinSAD < prevMB->sad16))) {
1590                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1591                          goto PMVfast16_Terminate_without_Refine;                          goto PMVfast16_Terminate_without_Refine;
1592                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1466  Line 1613 
1613    
1614          backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
1615    
1616    
1617  /* 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 */
1618          iSAD =          iSAD =
1619                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1620                                                    currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx,                                                    currMV->x, currMV->y, iMinSAD, &newMV, center_x, center_y,
1621                                                      min_dx, max_dx,
1622                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
1623                                                    iQuant, iFound);                                                    iQuant, iFound);
1624    
# Line 1484  Line 1633 
1633                  if (!(MVequal(pmv[0], backupMV))) {                  if (!(MVequal(pmv[0], backupMV))) {
1634                          iSAD =                          iSAD =
1635                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1636                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, pmv,                                                                    center_x, center_y, iMinSAD, &newMV, center_x, center_y,
1637                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1638                                                                    iDiamondSize, iFcode, iQuant, iFound);                                                                    iDiamondSize, iFcode, iQuant, iFound);
1639    
# Line 1497  Line 1646 
1646                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
1647                          iSAD =                          iSAD =
1648                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
1649                                                                    iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy,                                                                    iMinSAD, &newMV, center_x, center_y,
1650                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,                                                                    min_dx, max_dx, min_dy, max_dy,
1651                                                                      iEdgedWidth, iDiamondSize, iFcode,
1652                                                                    iQuant, iFound);                                                                    iQuant, iFound);
1653    
1654                          if (iSAD < iMinSAD) {                          if (iSAD < iMinSAD) {
# Line 1516  Line 1666 
1666          if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step
1667                  iMinSAD =                  iMinSAD =
1668                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
1669                                                           iMinSAD, pmv, min_dx, max_dx, min_dy, max_dy,                                                           iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
1670                                                           iFcode, iQuant, iEdgedWidth);                                                           iFcode, iQuant, iEdgedWidth);
1671    
1672    PMVfast16_Terminate_without_Refine:    PMVfast16_Terminate_without_Refine:
1673          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
1674          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
1675          return iMinSAD;          return iMinSAD;
1676  }  }
1677    
# Line 1538  Line 1688 
1688                                          const uint8_t * const cur,                                          const uint8_t * const cur,
1689                                          const int x,                                          const int x,
1690                                          const int y,                                          const int y,
1691                                          int32_t startx,                                          int32_t start_x,
1692                                          int32_t starty,                                          int32_t start_y,
1693                                          int32_t iMinSAD,                                          int32_t iMinSAD,
1694                                          VECTOR * const currMV,                                          VECTOR * const currMV,
1695                                          const VECTOR * const pmv,                                     const int center_x,
1696                                       const int center_y,
1697                                          const int32_t min_dx,                                          const int32_t min_dx,
1698                                          const int32_t max_dx,                                          const int32_t max_dx,
1699                                          const int32_t min_dy,                                          const int32_t min_dy,
# Line 1556  Line 1707 
1707  /* Do a diamond search around given starting point, return SAD of best */  /* Do a diamond search around given starting point, return SAD of best */
1708    
1709          int32_t iDirection = 0;          int32_t iDirection = 0;
1710            int32_t iDirectionBackup;
1711          int32_t iSAD;          int32_t iSAD;
1712          VECTOR backupMV;          VECTOR backupMV;
1713    
1714          backupMV.x = startx;          backupMV.x = start_x;
1715          backupMV.y = starty;          backupMV.y = start_y;
1716    
1717  /* 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 */
1718    
# Line 1569  Line 1721 
1721          CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);          CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);
1722          CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);          CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);
1723    
1724          if (iDirection)          if (iDirection) {
1725                  while (!iFound) {                  while (!iFound) {
1726                          iFound = 1;                          iFound = 1;
1727                          backupMV = *currMV;     // since iDirection!=0, this is well defined!                          backupMV = *currMV;     // since iDirection!=0, this is well defined!
1728                            iDirectionBackup = iDirection;
1729    
1730                          if (iDirection != 2)                          if (iDirectionBackup != 2)
1731                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1732                                                                                    backupMV.y, 1);                                                                                    backupMV.y, 1);
1733                          if (iDirection != 1)                          if (iDirectionBackup != 1)
1734                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1735                                                                                    backupMV.y, 2);                                                                                    backupMV.y, 2);
1736                          if (iDirection != 4)                          if (iDirectionBackup != 4)
1737                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1738                                                                                    backupMV.y - iDiamondSize, 3);                                                                                    backupMV.y - iDiamondSize, 3);
1739                          if (iDirection != 3)                          if (iDirectionBackup != 3)
1740                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1741                                                                                    backupMV.y + iDiamondSize, 4);                                                                                    backupMV.y + iDiamondSize, 4);
1742                    }
1743          } else {          } else {
1744                  currMV->x = startx;                  currMV->x = start_x;
1745                  currMV->y = starty;                  currMV->y = start_y;
1746          }          }
1747          return iMinSAD;          return iMinSAD;
1748  }  }
1749    
1750    
1751    
1752    
1753  int32_t  int32_t
1754  Halfpel8_Refine(const uint8_t * const pRef,  Square8_MainSearch(const uint8_t * const pRef,
1755                                  const uint8_t * const pRefH,                                  const uint8_t * const pRefH,
1756                                  const uint8_t * const pRefV,                                  const uint8_t * const pRefV,
1757                                  const uint8_t * const pRefHV,                                  const uint8_t * const pRefHV,
1758                                  const uint8_t * const cur,                                  const uint8_t * const cur,
1759                                  const int x,                                  const int x,
1760                                  const int y,                                  const int y,
1761                                  VECTOR * const currMV,                                          int32_t start_x,
1762                                            int32_t start_y,
1763                                  int32_t iMinSAD,                                  int32_t iMinSAD,
1764                                  const VECTOR * const pmv,                                          VECTOR * const currMV,
1765                                       const int center_x,
1766                                       const int center_y,
1767                                  const int32_t min_dx,                                  const int32_t min_dx,
1768                                  const int32_t max_dx,                                  const int32_t max_dx,
1769                                  const int32_t min_dy,                                  const int32_t min_dy,
1770                                  const int32_t max_dy,                                  const int32_t max_dy,
1771                                            const int32_t iEdgedWidth,
1772                                            const int32_t iDiamondSize,
1773                                  const int32_t iFcode,                                  const int32_t iFcode,
1774                                  const int32_t iQuant,                                  const int32_t iQuant,
1775                                  const int32_t iEdgedWidth)                                          int iFound)
1776  {  {
1777  /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */  /* Do a square search around given starting point, return SAD of best */
1778    
1779            int32_t iDirection = 0;
1780          int32_t iSAD;          int32_t iSAD;
1781          VECTOR backupMV = *currMV;          VECTOR backupMV;
   
         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);  
         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);  
   
         return iMinSAD;  
 }  
1782    
1783            backupMV.x = start_x;
1784            backupMV.y = start_y;
1785    
1786  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)  /* It's one search with full square pattern, and new parts for all following diamonds */
1787    
1788  int32_t  /*   new direction are extra, so 1-4 is normal diamond
1789  PMVfastSearch8(const uint8_t * const pRef,        537
1790                             const uint8_t * const pRefH,        1*2
1791                             const uint8_t * const pRefV,        648
1792                             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)  
 {  
         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;  
1793    
1794          const uint8_t *cur = pCur->y + x * 8 + y * 8 * iEdgedWidth;          CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y, 1);
1795            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y, 2);
1796            CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);
1797            CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);
1798    
1799          int32_t iDiamondSize;          CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize,
1800                                                             backupMV.y - iDiamondSize, 5);
1801            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize,
1802                                                             backupMV.y + iDiamondSize, 6);
1803            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize,
1804                                                             backupMV.y - iDiamondSize, 7);
1805            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize,
1806                                                             backupMV.y + iDiamondSize, 8);
1807    
         int32_t min_dx;  
         int32_t max_dx;  
         int32_t min_dy;  
         int32_t max_dy;  
1808    
1809          VECTOR pmv[4];          if (iDirection) {
1810          int32_t psad[4];                  while (!iFound) {
1811          VECTOR newMV;                          iFound = 1;
1812          VECTOR backupMV;                          backupMV = *currMV;
         VECTOR startMV;  
1813    
1814  //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;                          switch (iDirection) {
1815          const MACROBLOCK *const prevMB = prevMBs + (x >> 1) + (y >> 1) * iWcount;                          case 1:
1816                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1817                                                                                       backupMV.y, 1);
1818                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1819                                                                                     backupMV.y - iDiamondSize, 5);
1820                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1821                                                                                     backupMV.y - iDiamondSize, 7);
1822                                    break;
1823                            case 2:
1824                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1825                                                                                     2);
1826                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1827                                                                                     backupMV.y + iDiamondSize, 6);
1828                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1829                                                                                     backupMV.y + iDiamondSize, 8);
1830                                    break;
1831    
1832          static int32_t threshA, threshB;                          case 3:
1833          int32_t iFound, bPredEq;                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1834          int32_t iMinSAD, iSAD;                                                                                   4);
1835                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1836                                                                                     backupMV.y - iDiamondSize, 7);
1837                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1838                                                                                     backupMV.y + iDiamondSize, 8);
1839                                    break;
1840    
1841          int32_t iSubBlock = (y & 1) + (y & 1) + (x & 1);                          case 4:
1842                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1843                                                                                     3);
1844                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1845                                                                                     backupMV.y - iDiamondSize, 5);
1846                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1847                                                                                     backupMV.y + iDiamondSize, 6);
1848                                    break;
1849    
1850          MainSearch8FuncPtr MainSearchPtr;                          case 5:
1851                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
1852                                                                                     1);
1853                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1854                                                                                     3);
1855                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1856                                                                                     backupMV.y - iDiamondSize, 5);
1857                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1858                                                                                     backupMV.y + iDiamondSize, 6);
1859                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1860                                                                                     backupMV.y - iDiamondSize, 7);
1861                                    break;
1862    
1863          /* Init variables */                          case 6:
1864          startMV.x = start_x;                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1865          startMV.y = start_y;                                                                                   2);
1866                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1867                                                                                     3);
1868    
1869          /* Get maximum range */                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1870          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 8, iWidth, iHeight,                                                                                   backupMV.y - iDiamondSize, 5);
1871                            iFcode);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1872                                                                                     backupMV.y + iDiamondSize, 6);
1873                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1874                                                                                     backupMV.y + iDiamondSize, 8);
1875    
1876          if (!(MotionFlags & PMV_HALFPELDIAMOND8)) {                                  break;
1877                  min_dx = EVEN(min_dx);  
1878                  max_dx = EVEN(max_dx);                          case 7:
1879                  min_dy = EVEN(min_dy);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1880                  max_dy = EVEN(max_dy);                                                                                     backupMV.y, 1);
1881          }                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1882                                                                                     4);
1883                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1884                                                                                     backupMV.y - iDiamondSize, 5);
1885                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1886                                                                                     backupMV.y - iDiamondSize, 7);
1887                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1888                                                                                     backupMV.y + iDiamondSize, 8);
1889                                    break;
1890    
1891                            case 8:
1892                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1893                                                                                     2);
1894                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1895                                                                                     4);
1896                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1897                                                                                     backupMV.y + iDiamondSize, 6);
1898                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1899                                                                                     backupMV.y - iDiamondSize, 7);
1900                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1901                                                                                     backupMV.y + iDiamondSize, 8);
1902                                    break;
1903                            default:
1904                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
1905                                                                                     1);
1906                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1907                                                                                     2);
1908                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1909                                                                                     3);
1910                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1911                                                                                     4);
1912    
1913                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1914                                                                                     backupMV.y - iDiamondSize, 5);
1915                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1916                                                                                     backupMV.y + iDiamondSize, 6);
1917                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1918                                                                                     backupMV.y - iDiamondSize, 7);
1919                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1920                                                                                     backupMV.y + iDiamondSize, 8);
1921                                    break;
1922                            }
1923                    }
1924            } else {
1925                    currMV->x = start_x;
1926                    currMV->y = start_y;
1927            }
1928            return iMinSAD;
1929    }
1930    
1931    
1932    
1933    
1934    
1935    int32_t
1936    Halfpel8_Refine_c(const uint8_t * const pRef,
1937                                    const uint8_t * const pRefH,
1938                                    const uint8_t * const pRefV,
1939                                    const uint8_t * const pRefHV,
1940                                    const uint8_t * const cur,
1941                                    const int x,
1942                                    const int y,
1943                                    VECTOR * const currMV,
1944                                    int32_t iMinSAD,
1945                               const int center_x,
1946                               const int center_y,
1947                                    const int32_t min_dx,
1948                                    const int32_t max_dx,
1949                                    const int32_t min_dy,
1950                                    const int32_t max_dy,
1951                                    const int32_t iFcode,
1952                                    const int32_t iQuant,
1953                                    const int32_t iEdgedWidth)
1954    {
1955    /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */
1956    
1957            int32_t iSAD;
1958            VECTOR backupMV = *currMV;
1959    
1960            CHECK_MV8_CANDIDATE(backupMV.x - 1, backupMV.y - 1);
1961            CHECK_MV8_CANDIDATE(backupMV.x, backupMV.y - 1);
1962            CHECK_MV8_CANDIDATE(backupMV.x + 1, backupMV.y - 1);
1963            CHECK_MV8_CANDIDATE(backupMV.x - 1, backupMV.y);
1964            CHECK_MV8_CANDIDATE(backupMV.x + 1, backupMV.y);
1965            CHECK_MV8_CANDIDATE(backupMV.x - 1, backupMV.y + 1);
1966            CHECK_MV8_CANDIDATE(backupMV.x, backupMV.y + 1);
1967            CHECK_MV8_CANDIDATE(backupMV.x + 1, backupMV.y + 1);
1968    
1969            return iMinSAD;
1970    }
1971    
1972    
1973    #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)
1974    
1975    int32_t
1976    PMVfastSearch8(const uint8_t * const pRef,
1977                               const uint8_t * const pRefH,
1978                               const uint8_t * const pRefV,
1979                               const uint8_t * const pRefHV,
1980                               const IMAGE * const pCur,
1981                               const int x,
1982                               const int y,
1983                               const int start_x,
1984                               const int start_y,
1985                                    const int center_x,
1986                                    const int center_y,
1987                               const uint32_t MotionFlags,
1988                               const uint32_t iQuant,
1989                               const uint32_t iFcode,
1990                               const MBParam * const pParam,
1991                               const MACROBLOCK * const pMBs,
1992                               const MACROBLOCK * const prevMBs,
1993                               VECTOR * const currMV,
1994                               VECTOR * const currPMV)
1995    {
1996            const uint32_t iWcount = pParam->mb_width;
1997            const int32_t iWidth = pParam->width;
1998            const int32_t iHeight = pParam->height;
1999            const int32_t iEdgedWidth = pParam->edged_width;
2000    
2001            const uint8_t *cur = pCur->y + x * 8 + y * 8 * iEdgedWidth;
2002    
2003            int32_t iDiamondSize;
2004    
2005            int32_t min_dx;
2006            int32_t max_dx;
2007            int32_t min_dy;
2008            int32_t max_dy;
2009    
2010            VECTOR pmv[4];
2011            int32_t psad[4];
2012            VECTOR newMV;
2013            VECTOR backupMV;
2014            VECTOR startMV;
2015    
2016    //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
2017            const MACROBLOCK *const prevMB = prevMBs + (x >> 1) + (y >> 1) * iWcount;
2018    
2019             int32_t threshA, threshB;
2020            int32_t iFound, bPredEq;
2021            int32_t iMinSAD, iSAD;
2022    
2023            int32_t iSubBlock = (y & 1) + (y & 1) + (x & 1);
2024    
2025            MainSearch8FuncPtr MainSearchPtr;
2026    
2027            /* Init variables */
2028            startMV.x = start_x;
2029            startMV.y = start_y;
2030    
2031            /* Get maximum range */
2032            get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 8, iWidth, iHeight,
2033                              iFcode);
2034    
2035            if (!(MotionFlags & PMV_HALFPELDIAMOND8)) {
2036                    min_dx = EVEN(min_dx);
2037                    max_dx = EVEN(max_dx);
2038                    min_dy = EVEN(min_dy);
2039                    max_dy = EVEN(max_dy);
2040            }
2041    
2042          /* because we might use IF (dx>max_dx) THEN dx=max_dx; */          /* because we might use IF (dx>max_dx) THEN dx=max_dx; */
2043          bPredEq =          //bPredEq = get_pmvdata(pMBs, (x >> 1), (y >> 1), iWcount, iSubBlock, pmv, psad);
2044                  get_pmvdata(pMBs, (x >> 1), (y >> 1), iWcount, iSubBlock, pmv, psad);          bPredEq = get_pmvdata2(pMBs, iWcount, 0, (x >> 1), (y >> 1), iSubBlock, pmv, psad);
2045    
2046          if ((x == 0) && (y == 0)) {          if ((x == 0) && (y == 0)) {
2047                  threshA = 512 / 4;                  threshA = 512 / 4;
2048                  threshB = 1024 / 4;                  threshB = 1024 / 4;
2049    
2050          } else {          } else {
2051                  threshA = psad[0] / 4;  /* good estimate */                  threshA = psad[0] / 4;  /* good estimate? */
2052                  threshB = threshA + 256 / 4;                  threshB = threshA + 256 / 4;
2053                  if (threshA < 512 / 4)                  if (threshA < 512 / 4)
2054                          threshA = 512 / 4;                          threshA = 512 / 4;
# Line 1728  Line 2070 
2070    
2071  // Prepare for main loop  // Prepare for main loop
2072    
2073  //  if (MotionFlags & PMV_USESQUARES8)    if (MotionFlags & PMV_USESQUARES8)
2074  //      MainSearchPtr = Square8_MainSearch;        MainSearchPtr = Square8_MainSearch;
2075  //  else    else
2076    
2077          if (MotionFlags & PMV_ADVANCEDDIAMOND8)          if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2078                  MainSearchPtr = AdvDiamond8_MainSearch;                  MainSearchPtr = AdvDiamond8_MainSearch;
# Line 1745  Line 2087 
2087                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
2088                                                  iEdgedWidth), iEdgedWidth);                                                  iEdgedWidth), iEdgedWidth);
2089          iMinSAD +=          iMinSAD +=
2090                  calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y,                  calc_delta_8(currMV->x - center_x, currMV->y - center_y,
2091                                           (uint8_t) iFcode, iQuant);                                           (uint8_t) iFcode, iQuant);
2092    
2093          if ((iMinSAD < 256 / 4) || ((MVequal(*currMV, prevMB->mvs[iSubBlock]))          if ((iMinSAD < 256 / 4) || ((MVequal(*currMV, prevMB->mvs[iSubBlock]))
2094                                                                  && ((uint32_t) iMinSAD <                                                                  && ((int32_t) iMinSAD <
2095                                                                          prevMB->sad8[iSubBlock]))) {                                                                          prevMB->sad8[iSubBlock]))) {
2096                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
2097                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
# Line 1788  Line 2130 
2130  // the median prediction might be even better than mv16  // the median prediction might be even better than mv16
2131    
2132          if (!MVequal(pmv[0], startMV))          if (!MVequal(pmv[0], startMV))
2133                  CHECK_MV8_CANDIDATE(pmv[0].x, pmv[0].y);                  CHECK_MV8_CANDIDATE(center_x, center_y);
2134    
2135  // (0,0) if needed  // (0,0) if needed
2136          if (!MVzero(pmv[0]))          if (!MVzero(pmv[0]))
# Line 1804  Line 2146 
2146    
2147          if ((iMinSAD <= threshA) ||          if ((iMinSAD <= threshA) ||
2148                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
2149                   ((uint32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {                   ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
2150                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
2151                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
2152                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1863  Line 2205 
2205    
2206          if ((iMinSAD <= threshA) ||          if ((iMinSAD <= threshA) ||
2207                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
2208                   ((uint32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {                   ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
2209                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
2210                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
2211                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1885  Line 2227 
2227  /* 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 */
2228          iSAD =          iSAD =
2229                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2230                                                    currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx,                                                    currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2231                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2232                                                    iQuant, iFound);                                                    iQuant, iFound);
2233    
# Line 1900  Line 2242 
2242                  if (!(MVequal(pmv[0], backupMV))) {                  if (!(MVequal(pmv[0], backupMV))) {
2243                          iSAD =                          iSAD =
2244                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2245                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, pmv,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2246                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2247                                                                    iDiamondSize, iFcode, iQuant, iFound);                                                                    iDiamondSize, iFcode, iQuant, iFound);
2248    
# Line 1913  Line 2255 
2255                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2256                          iSAD =                          iSAD =
2257                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2258                                                                    iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2259                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2260                                                                    iQuant, iFound);                                                                    iQuant, iFound);
2261    
# Line 1932  Line 2274 
2274          if (MotionFlags & PMV_HALFPELREFINE8)   // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)   // perform final half-pel step
2275                  iMinSAD =                  iMinSAD =
2276                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2277                                                          iMinSAD, pmv, min_dx, max_dx, min_dy, max_dy,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2278                                                          iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
2279    
2280    
2281    PMVfast8_Terminate_without_Refine:    PMVfast8_Terminate_without_Refine:
2282          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2283          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2284    
2285          return iMinSAD;          return iMinSAD;
2286  }  }
# Line 1951  Line 2293 
2293                           const IMAGE * const pCur,                           const IMAGE * const pCur,
2294                           const int x,                           const int x,
2295                           const int y,                           const int y,
2296                            const int start_x,
2297                            const int start_y,
2298                            const int center_x,
2299                            const int center_y,
2300                           const uint32_t MotionFlags,                           const uint32_t MotionFlags,
2301                           const uint32_t iQuant,                           const uint32_t iQuant,
2302                           const uint32_t iFcode,                           const uint32_t iFcode,
# Line 1986  Line 2332 
2332          const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;          const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
2333          MACROBLOCK *oldMB = NULL;          MACROBLOCK *oldMB = NULL;
2334    
2335          static int32_t thresh2;           int32_t thresh2;
2336          int32_t bPredEq;          int32_t bPredEq;
2337          int32_t iMinSAD, iSAD = 9999;          int32_t iMinSAD, iSAD = 9999;
2338    
# Line 2009  Line 2355 
2355                  max_dy = EVEN(max_dy);                  max_dy = EVEN(max_dy);
2356          }          }
2357          /* 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; */
2358          bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          //bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
2359            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
2360    
2361  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
2362          MinSAD=SAD          MinSAD=SAD
# Line 2020  Line 2367 
2367    
2368  // Prepare for main loop  // Prepare for main loop
2369    
2370          *currMV = pmv[0];                       /* current best := median prediction */          currMV->x = start_x;
2371            currMV->y = start_y;
2372    
2373          if (!(MotionFlags & PMV_HALFPEL16)) {          if (!(MotionFlags & PMV_HALFPEL16)) {
2374                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
2375                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
# Line 2042  Line 2391 
2391                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
2392                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
2393          iMinSAD +=          iMinSAD +=
2394                  calc_delta_16(currMV->x - pmv[0].x, currMV->y - pmv[0].y,                  calc_delta_16(currMV->x - center_x, currMV->y - center_y,
2395                                            (uint8_t) iFcode, iQuant);                                            (uint8_t) iFcode, iQuant);
2396    
2397  // thresh1 is fixed to 256  // thresh1 is fixed to 256
2398          if ((iMinSAD < 256) ||          if ((iMinSAD < 256) ||
2399                  ((MVequal(*currMV, prevMB->mvs[0])) &&                  ((MVequal(*currMV, prevMB->mvs[0])) &&
2400                   ((uint32_t) iMinSAD < prevMB->sad16))) {                   ((int32_t) iMinSAD < prevMB->sad16))) {
2401                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
2402                          goto EPZS16_Terminate_without_Refine;                          goto EPZS16_Terminate_without_Refine;
2403                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 2108  Line 2457 
2457    
2458          if ((iMinSAD <= thresh2)          if ((iMinSAD <= thresh2)
2459                  || (MVequal(*currMV, prevMB->mvs[0]) &&                  || (MVequal(*currMV, prevMB->mvs[0]) &&
2460                          ((uint32_t) iMinSAD <= prevMB->sad16))) {                          ((int32_t) iMinSAD <= prevMB->sad16))) {
2461                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
2462                          goto EPZS16_Terminate_without_Refine;                          goto EPZS16_Terminate_without_Refine;
2463                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 2154  Line 2503 
2503    
2504          backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
2505    
2506          if (MotionFlags & PMV_USESQUARES8)          if (MotionFlags & PMV_USESQUARES16)
2507                  MainSearchPtr = Square16_MainSearch;                  MainSearchPtr = Square16_MainSearch;
2508          else          else
2509           if (MotionFlags & PMV_ADVANCEDDIAMOND8)           if (MotionFlags & PMV_ADVANCEDDIAMOND16)
2510                  MainSearchPtr = AdvDiamond16_MainSearch;                  MainSearchPtr = AdvDiamond16_MainSearch;
2511          else          else
2512                  MainSearchPtr = Diamond16_MainSearch;                  MainSearchPtr = Diamond16_MainSearch;
# Line 2166  Line 2515 
2515    
2516          iSAD =          iSAD =
2517                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2518                                                    currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx,                                                    currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2519                                                    min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);                                                    min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2520    
2521          if (iSAD < iMinSAD) {          if (iSAD < iMinSAD) {
# Line 2181  Line 2530 
2530                  if (!(MVequal(pmv[0], backupMV))) {                  if (!(MVequal(pmv[0], backupMV))) {
2531                          iSAD =                          iSAD =
2532                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2533                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, pmv,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2534                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2535                                                                    2, iFcode, iQuant, 0);                                                                    2, iFcode, iQuant, 0);
2536                  }                  }
# Line 2194  Line 2543 
2543                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2544                          iSAD =                          iSAD =
2545                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2546                                                                    iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2547                                                                    max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);                                                                    max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2548    
2549                          if (iSAD < iMinSAD) {                          if (iSAD < iMinSAD) {
# Line 2210  Line 2559 
2559          if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step
2560                  iMinSAD =                  iMinSAD =
2561                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2562                                                           iMinSAD, pmv, min_dx, max_dx, min_dy, max_dy,                                                           iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2563                                                           iFcode, iQuant, iEdgedWidth);                                                           iFcode, iQuant, iEdgedWidth);
2564    
2565    EPZS16_Terminate_without_Refine:    EPZS16_Terminate_without_Refine:
2566    
2567          *oldMB = *prevMB;          *oldMB = *prevMB;
2568    
2569          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2570          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2571          return iMinSAD;          return iMinSAD;
2572  }  }
2573    
# Line 2233  Line 2582 
2582                          const int y,                          const int y,
2583                          const int start_x,                          const int start_x,
2584                          const int start_y,                          const int start_y,
2585                            const int center_x,
2586                            const int center_y,
2587                          const uint32_t MotionFlags,                          const uint32_t MotionFlags,
2588                          const uint32_t iQuant,                          const uint32_t iQuant,
2589                          const uint32_t iFcode,                          const uint32_t iFcode,
# Line 2287  Line 2638 
2638                  max_dy = EVEN(max_dy);                  max_dy = EVEN(max_dy);
2639          }          }
2640          /* 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; */
2641          bPredEq = get_pmvdata(pMBs, x >> 1, y >> 1, iWcount, iSubBlock, pmv, psad);          //bPredEq = get_pmvdata(pMBs, x >> 1, y >> 1, iWcount, iSubBlock, pmv[0].x, pmv[0].y, psad);
2642            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x >> 1, y >> 1, iSubBlock, pmv, psad);
2643    
2644    
2645  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
# Line 2322  Line 2674 
2674                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
2675                                                  iEdgedWidth), iEdgedWidth);                                                  iEdgedWidth), iEdgedWidth);
2676          iMinSAD +=          iMinSAD +=
2677                  calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y,                  calc_delta_8(currMV->x - center_x, currMV->y - center_y,
2678                                           (uint8_t) iFcode, iQuant);                                           (uint8_t) iFcode, iQuant);
2679    
2680    
# Line 2398  Line 2750 
2750    
2751  // there is no EPZS^2 for inter4v at the moment  // there is no EPZS^2 for inter4v at the moment
2752    
2753  //  if (MotionFlags & PMV_USESQUARES8)    if (MotionFlags & PMV_USESQUARES8)
2754  //      MainSearchPtr = Square8_MainSearch;        MainSearchPtr = Square8_MainSearch;
2755  //  else    else
2756    
2757          if (MotionFlags & PMV_ADVANCEDDIAMOND8)          if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2758                  MainSearchPtr = AdvDiamond8_MainSearch;                  MainSearchPtr = AdvDiamond8_MainSearch;
# Line 2409  Line 2761 
2761    
2762          iSAD =          iSAD =
2763                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2764                                                    currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx,                                                    currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2765                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2766                                                    iQuant, 0);                                                    iQuant, 0);
2767    
# Line 2425  Line 2777 
2777                  if (!(MVequal(pmv[0], backupMV))) {                  if (!(MVequal(pmv[0], backupMV))) {
2778                          iSAD =                          iSAD =
2779                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2780                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, pmv,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2781                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2782                                                                    iDiamondSize, iFcode, iQuant, 0);                                                                    iDiamondSize, iFcode, iQuant, 0);
2783    
# Line 2438  Line 2790 
2790                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2791                          iSAD =                          iSAD =
2792                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2793                                                                    iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2794                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2795                                                                    iQuant, 0);                                                                    iQuant, 0);
2796    
# Line 2455  Line 2807 
2807          if (MotionFlags & PMV_HALFPELREFINE8)   // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)   // perform final half-pel step
2808                  iMinSAD =                  iMinSAD =
2809                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2810                                                          iMinSAD, pmv, min_dx, max_dx, min_dy, max_dy,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2811                                                          iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
2812    
2813    EPZS8_Terminate_without_Refine:    EPZS8_Terminate_without_Refine:
2814    
2815          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2816          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2817          return iMinSAD;          return iMinSAD;
2818  }  }
2819    
2820    
2821    
2822    int32_t
2823    PMVfastIntSearch16(const uint8_t * const pRef,
2824                                    const uint8_t * const pRefH,
2825                                    const uint8_t * const pRefV,
2826                                    const uint8_t * const pRefHV,
2827                                    const IMAGE * const pCur,
2828                                    const int x,
2829                                    const int y,
2830                                    const int start_x,              /* start should be most likely vector */
2831                                    const int start_y,
2832                                    const int center_x,             /* center is from where length of MVs is measured */
2833                                    const int center_y,
2834                                    const uint32_t MotionFlags,
2835                                    const uint32_t iQuant,
2836                                    const uint32_t iFcode,
2837                                    const MBParam * const pParam,
2838                                    const MACROBLOCK * const pMBs,
2839                                    const MACROBLOCK * const prevMBs,
2840                                    VECTOR * const currMV,
2841                                    VECTOR * const currPMV)
2842    {
2843            const uint32_t iWcount = pParam->mb_width;
2844            const int32_t iWidth = pParam->width;
2845            const int32_t iHeight = pParam->height;
2846            const int32_t iEdgedWidth = pParam->edged_width;
2847    
2848            const uint8_t *cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;
2849            const VECTOR zeroMV = { 0, 0 };
2850    
2851            int32_t iDiamondSize;
2852    
2853            int32_t min_dx;
2854            int32_t max_dx;
2855            int32_t min_dy;
2856            int32_t max_dy;
2857    
2858            int32_t iFound;
2859    
2860            VECTOR newMV;
2861            VECTOR backupMV;
2862    
2863            VECTOR pmv[4];
2864            int32_t psad[4];
2865    
2866            MainSearch16FuncPtr MainSearchPtr;
2867    
2868            const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
2869            MACROBLOCK *const pMB = pMBs + x + y * iWcount;
2870    
2871            int32_t threshA, threshB;
2872            int32_t bPredEq;
2873            int32_t iMinSAD, iSAD;
2874    
2875    
2876    /* Get maximum range */
2877            get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
2878                              iFcode);
2879    
2880    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
2881    
2882            if ((x == 0) && (y == 0)) {
2883                    threshA = 512;
2884                    threshB = 1024;
2885    
2886                    bPredEq = 0;
2887                    psad[0] = psad[1] = psad[2] = psad[3] = 0;
2888                    *currMV = pmv[0] = pmv[1] = pmv[2] = pmv[3] = zeroMV;
2889    
2890            } else {
2891                    threshA = psad[0];
2892                    threshB = threshA + 256;
2893                    if (threshA < 512)
2894                            threshA = 512;
2895                    if (threshA > 1024)
2896                            threshA = 1024;
2897                    if (threshB > 1792)
2898                            threshB = 1792;
2899    
2900                    bPredEq = get_ipmvdata(pMBs, iWcount, 0, x, y, 0, pmv, psad);
2901                    *currMV = pmv[0];                       /* current best := prediction */
2902            }
2903    
2904            iFound = 0;
2905    
2906    /* Step 4: Calculate SAD around the Median prediction.
2907       MinSAD=SAD
2908       If Motion Vector equal to Previous frame motion vector
2909       and MinSAD<PrevFrmSAD goto Step 10.
2910       If SAD<=256 goto Step 10.
2911    */
2912    
2913            if (currMV->x > max_dx) {
2914                    currMV->x = EVEN(max_dx);
2915            }
2916            if (currMV->x < min_dx) {
2917                    currMV->x = EVEN(min_dx);
2918            }
2919            if (currMV->y > max_dy) {
2920                    currMV->y = EVEN(max_dy);
2921            }
2922            if (currMV->y < min_dy) {
2923                    currMV->y = EVEN(min_dy);
2924            }
2925    
2926            iMinSAD =
2927                    sad16(cur,
2928                              get_iref_mv(pRef, x, y, 16, currMV,
2929                                                     iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
2930            iMinSAD +=
2931                    calc_delta_16(currMV->x - center_x, currMV->y - center_y,
2932                                              (uint8_t) iFcode, iQuant);
2933    
2934            if ((iMinSAD < 256) ||
2935                    ((MVequal(*currMV, prevMB->i_mvs[0])) &&
2936                     ((int32_t) iMinSAD < prevMB->i_sad16))) {
2937                    if (iMinSAD < 2 * iQuant)       // high chances for SKIP-mode
2938                    {
2939                            if (!MVzero(*currMV)) {
2940                                    iMinSAD += MV16_00_BIAS;
2941                                    CHECK_MV16_ZERO;        // (0,0) saves space for letterboxed pictures
2942                                    iMinSAD -= MV16_00_BIAS;
2943                            }
2944                    }
2945    
2946                    if (MotionFlags & PMV_EARLYSTOP16)
2947                            goto PMVfastInt16_Terminate_with_Refine;
2948            }
2949    
2950    
2951    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
2952       vector of the median.
2953       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
2954    */
2955    
2956            if ((bPredEq) && (MVequal(pmv[0], prevMB->i_mvs[0])))
2957                    iFound = 2;
2958    
2959    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
2960       Otherwise select large Diamond Search.
2961    */
2962    
2963            if ((!MVzero(pmv[0])) || (threshB < 1536) || (bPredEq))
2964                    iDiamondSize = 2;               // halfpel units!
2965            else
2966                    iDiamondSize = 4;               // halfpel units!
2967    
2968    /*
2969       Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.
2970       Also calculate (0,0) but do not subtract offset.
2971       Let MinSAD be the smallest SAD up to this point.
2972       If MV is (0,0) subtract offset.
2973    */
2974    
2975    // (0,0) is often a good choice
2976    
2977            if (!MVzero(pmv[0]))
2978                    CHECK_MV16_ZERO;
2979    
2980    // previous frame MV is always possible
2981    
2982            if (!MVzero(prevMB->i_mvs[0]))
2983                    if (!MVequal(prevMB->i_mvs[0], pmv[0]))
2984                            CHECK_MV16_CANDIDATE(prevMB->i_mvs[0].x, prevMB->i_mvs[0].y);
2985    
2986    // left neighbour, if allowed
2987    
2988            if (!MVzero(pmv[1]))
2989                    if (!MVequal(pmv[1], prevMB->i_mvs[0]))
2990                            if (!MVequal(pmv[1], pmv[0]))
2991                                    CHECK_MV16_CANDIDATE(pmv[1].x, pmv[1].y);
2992    
2993    // top neighbour, if allowed
2994            if (!MVzero(pmv[2]))
2995                    if (!MVequal(pmv[2], prevMB->i_mvs[0]))
2996                            if (!MVequal(pmv[2], pmv[0]))
2997                                    if (!MVequal(pmv[2], pmv[1]))
2998                                            CHECK_MV16_CANDIDATE(pmv[2].x, pmv[2].y);
2999    
3000    // top right neighbour, if allowed
3001                                            if (!MVzero(pmv[3]))
3002                                                    if (!MVequal(pmv[3], prevMB->i_mvs[0]))
3003                                                            if (!MVequal(pmv[3], pmv[0]))
3004                                                                    if (!MVequal(pmv[3], pmv[1]))
3005                                                                            if (!MVequal(pmv[3], pmv[2]))
3006                                                                                    CHECK_MV16_CANDIDATE(pmv[3].x,
3007                                                                                                                             pmv[3].y);
3008    
3009            if ((MVzero(*currMV)) &&
3010                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
3011                    iMinSAD -= MV16_00_BIAS;
3012    
3013    
3014    /* Step 6: If MinSAD <= thresa goto Step 10.
3015       If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
3016    */
3017    
3018            if ((iMinSAD <= threshA) ||
3019                    (MVequal(*currMV, prevMB->i_mvs[0]) &&
3020                     ((int32_t) iMinSAD < prevMB->i_sad16))) {
3021    
3022                    if (MotionFlags & PMV_EARLYSTOP16)
3023                            goto PMVfastInt16_Terminate_with_Refine;
3024            }
3025    
3026    
3027    /************ (Diamond Search)  **************/
3028    /*
3029       Step 7: Perform Diamond search, with either the small or large diamond.
3030       If Found=2 only examine one Diamond pattern, and afterwards goto step 10
3031       Step 8: If small diamond, iterate small diamond search pattern until motion vector lies in the center of the diamond.
3032       If center then goto step 10.
3033       Step 9: If large diamond, iterate large diamond search pattern until motion vector lies in the center.
3034       Refine by using small diamond and goto step 10.
3035    */
3036    
3037            if (MotionFlags & PMV_USESQUARES16)
3038                    MainSearchPtr = Square16_MainSearch;
3039            else if (MotionFlags & PMV_ADVANCEDDIAMOND16)
3040                    MainSearchPtr = AdvDiamond16_MainSearch;
3041            else
3042                    MainSearchPtr = Diamond16_MainSearch;
3043    
3044            backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
3045    
3046    
3047    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
3048            iSAD =
3049                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
3050                                                      currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
3051                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
3052                                                      iQuant, iFound);
3053    
3054            if (iSAD < iMinSAD) {
3055                    *currMV = newMV;
3056                    iMinSAD = iSAD;
3057            }
3058    
3059            if (MotionFlags & PMV_EXTSEARCH16) {
3060    /* extended: search (up to) two more times: orignal prediction and (0,0) */
3061    
3062                    if (!(MVequal(pmv[0], backupMV))) {
3063                            iSAD =
3064                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
3065                                                                      pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
3066                                                                      min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
3067                                                                      iDiamondSize, iFcode, iQuant, iFound);
3068    
3069                            if (iSAD < iMinSAD) {
3070                                    *currMV = newMV;
3071                                    iMinSAD = iSAD;
3072                            }
3073                    }
3074    
3075                    if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
3076                            iSAD =
3077                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
3078                                                                      iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
3079                                                                      max_dy, iEdgedWidth, iDiamondSize, iFcode,
3080                                                                      iQuant, iFound);
3081    
3082                            if (iSAD < iMinSAD) {
3083                                    *currMV = newMV;
3084                                    iMinSAD = iSAD;
3085                            }
3086                    }
3087            }
3088    
3089    /*
3090       Step 10:  The motion vector is chosen according to the block corresponding to MinSAD.
3091    */
3092    
3093    PMVfastInt16_Terminate_with_Refine:
3094    
3095            pMB->i_mvs[0] = pMB->i_mvs[1] = pMB->i_mvs[2] = pMB->i_mvs[3] = pMB->i_mv16 = *currMV;
3096            pMB->i_sad8[0] = pMB->i_sad8[1] = pMB->i_sad8[2] = pMB->i_sad8[3] = pMB->i_sad16 = iMinSAD;
3097    
3098            if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step
3099                    iMinSAD =
3100                            Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
3101                                                             iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
3102                                                             iFcode, iQuant, iEdgedWidth);
3103    
3104            pmv[0] = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);          // get _REAL_ prediction (halfpel possible)
3105    
3106    PMVfastInt16_Terminate_without_Refine:
3107            currPMV->x = currMV->x - center_x;
3108            currPMV->y = currMV->y - center_y;
3109            return iMinSAD;
3110    }
3111    
3112    
3113    
3114  /* ***********************************************************  /* ***********************************************************
3115          bvop motion estimation          bvop motion estimation
 // TODO: need to incorporate prediction here (eg. sad += calc_delta_16)  
3116  ***************************************************************/  ***************************************************************/
3117    
   
3118  void  void
3119  MotionEstimationBVOP(MBParam * const pParam,  MotionEstimationBVOP(MBParam * const pParam,
3120                                           FRAMEINFO * const frame,                                           FRAMEINFO * const frame,
3121                                             const int32_t time_bp,
3122                                             const int32_t time_pp,
3123                                           // forward (past) reference                                           // forward (past) reference
3124                                           const MACROBLOCK * const f_mbs,                                           const MACROBLOCK * const f_mbs,
3125                                           const IMAGE * const f_ref,                                           const IMAGE * const f_ref,
# Line 2491  Line 3133 
3133                                           const IMAGE * const b_refV,                                           const IMAGE * const b_refV,
3134                                           const IMAGE * const b_refHV)                                           const IMAGE * const b_refHV)
3135  {  {
3136          const uint32_t mb_width = pParam->mb_width;          const int mb_width = pParam->mb_width;
3137          const uint32_t mb_height = pParam->mb_height;          const int mb_height = pParam->mb_height;
3138          const int32_t edged_width = pParam->edged_width;          const int edged_width = pParam->edged_width;
3139    
3140          uint32_t i, j;          const int32_t iWidth = pParam->width;
3141            const int32_t iHeight = pParam->height;
3142          int32_t f_sad16;  
3143          int32_t b_sad16;          int i, j, k;
3144          int32_t i_sad16;  
3145          int32_t d_sad16;          static const VECTOR zeroMV={0,0};
3146          int32_t best_sad;  
3147            int f_sad16;    /* forward (as usual) search */
3148            int b_sad16;    /* backward (only in b-frames) search */
3149            int i_sad16;    /* interpolated (both direction, b-frames only) */
3150            int d_sad16;    /* direct mode (assume almost linear motion) */
3151    
3152            int best_sad;
3153    
3154            VECTOR f_predMV, b_predMV;      /* there is no prediction for direct mode*/
3155            VECTOR f_interpolMV, b_interpolMV;
3156          VECTOR pmv_dontcare;          VECTOR pmv_dontcare;
3157    
3158            int min_dx, max_dx, min_dy, max_dy;
3159            int f_min_dx, f_max_dx, f_min_dy, f_max_dy;
3160            int b_min_dx, b_max_dx, b_min_dy, b_max_dy;
3161    
3162            int f_count=0;
3163            int b_count=0;
3164            int i_count=0;
3165            int d_count=0;
3166    
3167            const int64_t TRB = (int32_t)time_pp - (int32_t)time_bp;
3168        const int64_t TRD = (int32_t)time_pp;
3169    
3170            // fprintf(stderr,"TRB = %lld  TRD = %lld  time_bp =%d time_pp =%d\n\n",TRB,TRD,time_bp,time_pp);
3171          // note: i==horizontal, j==vertical          // note: i==horizontal, j==vertical
3172          for (j = 0; j < mb_height; j++) {          for (j = 0; j < mb_height; j++) {
3173    
3174                    f_predMV = zeroMV;      /* prediction is reset at left boundary */
3175                    b_predMV = zeroMV;
3176    
3177                  for (i = 0; i < mb_width; i++) {                  for (i = 0; i < mb_width; i++) {
3178                          MACROBLOCK *mb = &frame->mbs[i + j * mb_width];                          MACROBLOCK *mb = &frame->mbs[i + j * mb_width];
3179                          const MACROBLOCK *f_mb = &f_mbs[i + j * mb_width];                          const MACROBLOCK *f_mb = &f_mbs[i + j * mb_width];
3180                          const MACROBLOCK *b_mb = &b_mbs[i + j * mb_width];                          const MACROBLOCK *b_mb = &b_mbs[i + j * mb_width];
3181    
3182                            mb->deltamv=zeroMV;
3183    
3184    /* special case, if collocated block is SKIPed: encoding is forward (0,0), cpb=0 without further ado */
3185    
3186                          if (b_mb->mode == MODE_INTER && b_mb->cbp == 0 &&                          if (b_mb->mode == MODE_INTER && b_mb->cbp == 0 &&
3187                                  b_mb->mvs[0].x == 0 && b_mb->mvs[0].y == 0) {                                  b_mb->mvs[0].x == 0 && b_mb->mvs[0].y == 0) {
3188                                  mb->mode = MODE_NOT_CODED;                                  mb->mode = MODE_NOT_CODED;
3189                                  mb->mvs[0].x = 0;                                  mb->b_mvs[0] = mb->mvs[0] = zeroMV;
                                 mb->mvs[0].y = 0;  
                                 mb->b_mvs[0].x = 0;  
                                 mb->b_mvs[0].y = 0;  
3190                                  continue;                                  continue;
3191                          }                          }
                 /* force F_SAD16  
                         f_sad16 = 100;  
                         b_sad16 = 65535;  
3192    
3193                          mb->mode = MODE_FORWARD;                          if (b_mb->mode == MODE_INTER4V)
3194                          mb->mvs[0].x = 1;                          {
3195                          mb->mvs[0].y = 1;                                  d_sad16 = 0;
3196                          mb->b_mvs[0].x = 1;                          /* same method of scaling as in decoder.c, so we copy from there */
3197                          mb->b_mvs[0].y = 1;                      for (k = 0; k < 4; k++) {
3198                          continue;  
3199                   ^^ force F_SAD16 */                                          mb->directmv[k] = b_mb->mvs[k];
3200    
3201                                            mb->mvs[k].x = (int32_t) ((TRB * mb->directmv[k].x) / TRD + mb->deltamv.x);
3202                        mb->b_mvs[k].x = (int32_t) ((mb->deltamv.x == 0)
3203                                                                                    ? ((TRB - TRD) * mb->directmv[k].x) / TRD
3204                                                : mb->mvs[k].x - mb->directmv[k].x);
3205    
3206                        mb->mvs[k].y = (int32_t) ((TRB * mb->directmv[k].y) / TRD + mb->deltamv.y);
3207                            mb->b_mvs[k].y = (int32_t) ((mb->deltamv.y == 0)
3208                                                                                    ? ((TRB - TRD) * mb->directmv[k].y) / TRD
3209                                                : mb->mvs[k].y - mb->directmv[k].y);
3210    
3211                                            d_sad16 +=
3212                                                    sad8bi(frame->image.y + (2*i+(k&1))*8 + (2*j+(k>>1))*8*edged_width,
3213                                                      get_ref_mv(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3214                                                                    (2*i+(k&1)), (2*j+(k>>1)), 8, &mb->mvs[k], edged_width),
3215                                                      get_ref_mv(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3216                                                                    (2*i+(k&1)), (2*j+(k>>1)), 8, &mb->b_mvs[k], edged_width),
3217                                                      edged_width);
3218                                    }
3219                            }
3220                            else
3221                            {
3222                                    mb->directmv[3] = mb->directmv[2] = mb->directmv[1] =
3223                                            mb->directmv[0] = b_mb->mvs[0];
3224    
3225                                    mb->mvs[0].x = (int32_t) ((TRB * mb->directmv[0].x) / TRD + mb->deltamv.x);
3226                        mb->b_mvs[0].x = (int32_t) ((mb->deltamv.x == 0)
3227                                                                            ? ((TRB - TRD) * mb->directmv[0].x) / TRD
3228                                        : mb->mvs[0].x - mb->directmv[0].x);
3229    
3230                        mb->mvs[0].y = (int32_t) ((TRB * mb->directmv[0].y) / TRD + mb->deltamv.y);
3231                    mb->b_mvs[0].y = (int32_t) ((mb->directmv[0].y == 0)
3232                                                                            ? ((TRB - TRD) * mb->directmv[0].y) / TRD
3233                                        : mb->mvs[0].y - mb->directmv[0].y);
3234    
3235                                    d_sad16 = sad16bi(frame->image.y + i * 16 + j * 16 * edged_width,
3236                                                      get_ref_mv(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3237                                                                    i, j, 16, &mb->mvs[0], edged_width),
3238                                                      get_ref_mv(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3239                                                                    i, j, 16, &mb->b_mvs[0], edged_width),
3240                                                      edged_width);
3241    
3242                }
3243                        d_sad16 += calc_delta_16(mb->deltamv.x, mb->deltamv.y, 1, frame->quant);
3244    
3245                          // forward search                          // forward search
3246                          f_sad16 =                          f_sad16 = SEARCH16(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3247                                  SEARCH16(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,                                                  &frame->image, i, j,
3248                                                   &frame->image, i, j, frame->motion_flags,                                                  mb->mvs[0].x, mb->mvs[0].y,                     /* start point f_directMV */
3249                                                    f_predMV.x, f_predMV.y,                         /* center is f-prediction */
3250                                                    frame->motion_flags,
3251                                                   frame->quant, frame->fcode, pParam,                                                   frame->quant, frame->fcode, pParam,
3252                                                   f_mbs,  f_mbs, /* todo */                                                  f_mbs, f_mbs,
3253                                                   &mb->mvs[0], &pmv_dontcare);   // ignore pmv                                                  &mb->mvs[0], &pmv_dontcare);
3254    
3255    
3256                          // backward search                          // backward search
3257                          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,
3258                                                  &frame->image, i, j, frame->motion_flags,                                                  &frame->image, i, j,
3259                                                    mb->b_mvs[0].x, mb->b_mvs[0].y,         /* start point b_directMV */
3260                                                    b_predMV.x, b_predMV.y,                         /* center is b-prediction */
3261                                                    frame->motion_flags,
3262                                                  frame->quant, frame->bcode, pParam,                                                  frame->quant, frame->bcode, pParam,
3263                                                  b_mbs, b_mbs,   /* todo */                                                  b_mbs, b_mbs,
3264                                                  &mb->b_mvs[0], &pmv_dontcare);  // ignore pmv                                                  &mb->b_mvs[0], &pmv_dontcare);
3265    
                         // interpolate search (simple, but effective)  
                         i_sad16 = 65535;  
   
                         /*  
                         x/y range somewhat buggy  
3266                          i_sad16 =                          i_sad16 =
3267                                  sad16bi_c(frame->image.y + i * 16 + j * 16 * edged_width,                                  sad16bi(frame->image.y + i * 16 + j * 16 * edged_width,
3268                                                    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,
3269                                                                    i, j, 16, mb->mvs[0].x, mb->mvs[0].y,                                                                  i, j, 16, &mb->mvs[0], edged_width),
3270                                                                    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,
3271                                                                                                                  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),  
3272                                                    edged_width);                                                    edged_width);
3273                          */                      i_sad16 += calc_delta_16(mb->mvs[0].x-f_predMV.x, mb->mvs[0].y-f_predMV.y,
3274                                                                    frame->fcode, frame->quant);
3275                          // TODO: direct search                      i_sad16 += calc_delta_16(mb->b_mvs[0].x-b_predMV.x, mb->b_mvs[0].y-b_predMV.y,
3276                          // predictor + range of [-32,32]                                                                  frame->bcode, frame->quant);
3277                          d_sad16 = 65535;  
3278                            get_range(&f_min_dx, &f_max_dx, &f_min_dy, &f_max_dy, i, j, 16, iWidth, iHeight,
3279                              frame->fcode);
3280                            get_range(&b_min_dx, &b_max_dx, &b_min_dy, &b_max_dy, i, j, 16, iWidth, iHeight,
3281                              frame->bcode);
3282    
3283    /* Interpolated MC motion vector search, this is tedious and more complicated because there are
3284       two values for everything, always one for backward and one for forward ME. Still, we don't gain
3285       much from this search, maybe it should simply be skipped and simply current i_sad16 value used
3286       as "optimal". */
3287    
3288                            i_sad16 = Diamond16_InterpolMainSearch(
3289                                                    f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3290                                                    frame->image.y + i * 16 + j * 16 * edged_width,
3291                                                    b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3292                                                    i, j,
3293                                                    mb->mvs[0].x, mb->mvs[0].y,
3294                                                    mb->b_mvs[0].x, mb->b_mvs[0].y,
3295                                                    i_sad16,
3296                                                    &f_interpolMV, &b_interpolMV,
3297                                                    f_predMV.x, f_predMV.y, b_predMV.x, b_predMV.y,
3298                                                    f_min_dx, f_max_dx, f_min_dy, f_max_dy,
3299                                                    b_min_dx, b_max_dx, b_min_dy, b_max_dy,
3300                                                    edged_width,  2,
3301                                                    frame->fcode, frame->bcode,frame->quant,0);
3302    
3303                            i_sad16 = Diamond16_InterpolMainSearch(
3304                                                    f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3305                                                    frame->image.y + i * 16 + j * 16 * edged_width,
3306                                                    b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3307                                                    i, j,
3308                                                    f_interpolMV.x, f_interpolMV.y,
3309                                                    b_interpolMV.x, b_interpolMV.y,
3310                                                    i_sad16,
3311                                                    &f_interpolMV, &b_interpolMV,
3312                                                    f_predMV.x, f_predMV.y, b_predMV.x, b_predMV.y,
3313                                                    f_min_dx, f_max_dx, f_min_dy, f_max_dy,
3314                                                    b_min_dx, b_max_dx, b_min_dy, b_max_dy,
3315                                                    edged_width,  1,
3316                                                    frame->fcode, frame->bcode,frame->quant,0);             // equiv to halfpel refine
3317    
3318    
3319    /*  DIRECT MODE DELTA VECTOR SEARCH.
3320        This has to be made more effective, but at the moment I'm happy it's running at all */
3321    
3322    /* There are two range restrictions for direct mode: deltaMV is limited to [-32,31] in halfpel units, and
3323       absolute vector must not lie outside of image dimensions. Constraint one is dealt with by CHECK_MV16_DIRECT
3324       and for constraint two we need distance to boundary. This is done by get_range very large fcode (hack!) */
3325    
3326                            get_range(&min_dx, &max_dx, &min_dy, &max_dy, i, j, 16, iWidth, iHeight, 19);
3327    
3328                            d_sad16 = Diamond16_DirectMainSearch(
3329                                                    f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3330                                                    frame->image.y + i*16 + j*16*edged_width,
3331                                                    b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3332                                                    i, j,
3333                                                    TRB,TRD,
3334                                                    0,0,
3335                                                    d_sad16,
3336                                                    &mb->deltamv,
3337                                                    mb->directmv, // this has to be pre-initialized with b_mb->mvs[]
3338                                            min_dx, max_dx, min_dy, max_dy,
3339                                                    edged_width, 2, frame->quant, 0);
3340    
3341                            d_sad16 = Diamond16_DirectMainSearch(
3342                                                    f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3343                                                    frame->image.y + i*16 + j*16*edged_width,
3344                                                    b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3345                                                    i, j,
3346                                                    TRB,TRD,
3347                                                    mb->deltamv.x, mb->deltamv.y,
3348                                                    d_sad16,
3349                                                    &mb->deltamv,
3350                                                    mb->directmv, // this has to be pre-initialized with b_mb->mvs[]
3351                                            min_dx, max_dx, min_dy, max_dy,
3352                                                    edged_width, 1, frame->quant, 0);               // equiv to halfpel refine
3353    
3354    
3355    //                      i_sad16 = 65535;                /* remove the comment to disable any of the MODEs */
3356    //                      f_sad16 = 65535;
3357    //                      b_sad16 = 65535;
3358    //                      d_sad16 = 65535;
3359    
3360                          if (f_sad16 < b_sad16) {                          if (f_sad16 < b_sad16) {
3361                                  best_sad = f_sad16;                                  best_sad = f_sad16;
# Line 2586  Line 3371 
3371                          }                          }
3372    
3373                          if (d_sad16 < best_sad) {                          if (d_sad16 < best_sad) {
3374    
3375                                    if (b_mb->mode == MODE_INTER4V)
3376                                    {
3377    
3378                                    /* how to calc vectors is defined in standard. mvs[] and b_mvs[] are only for motion compensation */
3379                                    /* for the bitstream, the value mb->deltamv is read directly */
3380    
3381                                for (k = 0; k < 4; k++) {
3382    
3383                                                    mb->mvs[k].x = (int32_t) ((TRB * mb->directmv[k].x) / TRD + mb->deltamv.x);
3384                                mb->b_mvs[k].x = (int32_t) ((mb->deltamv.x == 0)
3385                                                                                            ? ((TRB - TRD) * mb->directmv[k].x) / TRD
3386                                                        : mb->mvs[k].x - mb->directmv[k].x);
3387    
3388                                mb->mvs[k].y = (int32_t) ((TRB * mb->directmv[k].y) / TRD + mb->deltamv.y);
3389                            mb->b_mvs[k].y = (int32_t) ((mb->deltamv.y == 0)
3390                                                                                            ? ((TRB - TRD) * mb->directmv[k].y) / TRD
3391                                                : mb->mvs[k].y - mb->directmv[k].y);
3392                                            }
3393                                    }
3394                                    else
3395                                    {
3396                                            mb->mvs[0].x = (int32_t) ((TRB * mb->directmv[0].x) / TRD + mb->deltamv.x);
3397    
3398                        mb->b_mvs[0].x = (int32_t) ((mb->deltamv.x == 0)
3399                                                                                    ? ((TRB - TRD) * mb->directmv[0].x) / TRD
3400                                            : mb->mvs[0].x - mb->directmv[0].x);
3401    
3402                                mb->mvs[0].y = (int32_t) ((TRB * mb->directmv[0].y) / TRD + mb->deltamv.y);
3403    
3404                            mb->b_mvs[0].y = (int32_t) ((mb->deltamv.y == 0)
3405                                                                                    ? ((TRB - TRD) * mb->directmv[0].y) / TRD
3406                                                : mb->mvs[0].y - mb->directmv[0].y);
3407    
3408                                            mb->mvs[3] = mb->mvs[2] = mb->mvs[1] = mb->mvs[0];
3409                                            mb->b_mvs[3] = mb->b_mvs[2] = mb->b_mvs[1] = mb->b_mvs[0];
3410                    }
3411    
3412                                  best_sad = d_sad16;                                  best_sad = d_sad16;
3413                                  mb->mode = MODE_DIRECT;                                  mb->mode = MODE_DIRECT;
3414                          }                          }
3415    
3416                            switch (mb->mode)
3417                            {
3418                                    case MODE_FORWARD:
3419                                            f_count++;
3420                                            f_predMV = mb->mvs[0];
3421                                            break;
3422                                    case MODE_BACKWARD:
3423                                            b_count++;
3424                                            b_predMV = mb->b_mvs[0];
3425    
3426                                            break;
3427                                    case MODE_INTERPOLATE:
3428                                            i_count++;
3429                                            mb->mvs[0] = f_interpolMV;
3430                                            mb->b_mvs[0] = b_interpolMV;
3431                                            f_predMV = mb->mvs[0];
3432                                            b_predMV = mb->b_mvs[0];
3433                                            break;
3434                                    case MODE_DIRECT:
3435                                            d_count++;
3436                                            break;
3437                                    default:
3438                                            break;
3439                            }
3440    
3441                  }                  }
3442          }          }
3443    
3444    #ifdef _DEBUG_BFRAME_STAT
3445            fprintf(stderr,"B-Stat: F: %04d   B: %04d   I: %04d  D: %04d\n",
3446                                    f_count,b_count,i_count,d_count);
3447    #endif
3448    
3449  }  }

Legend:
Removed from v.252  
changed lines
  Added in v.351

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